annotate tccelf.c @ 570:c42c2145d359

The dynamic linker location belongs in configure, move it there.
author Rob Landley <rob@landley.net>
date Sat, 15 Mar 2008 21:23:24 -0500
parents d89a6822b7e0
children 6912ed120df3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1 /*
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2 * ELF file handling for TCC
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
3 *
331
417ae7104677 [project @ 2004-10-27 21:38:03 by bellard]
bellard
parents: 329
diff changeset
4 * Copyright (c) 2001-2004 Fabrice Bellard
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
5 *
499
2b451d2e68ea Exercise LGPL clause 3 and convert more notices from LGPL to GPLv2. (If you
Rob Landley <rob@landley.net>
parents: 481
diff changeset
6 * Licensed under GPLv2, see file LICENSE in this tarball.
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
7 */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
8
469
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
9 #include <limits.h>
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
10
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
11 static int put_elf_str(Section *s, char *sym)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
12 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
13 int offset, len;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
14 char *ptr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
15
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
16 len = strlen(sym) + 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
17 offset = s->data_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
18 ptr = section_ptr_add(s, len);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
19 memcpy(ptr, sym, len);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
20 return offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
21 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
22
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
23 /* elf symbol hashing function */
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
24 static unsigned long elf_hash(unsigned char *name)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
25 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
26 unsigned long h = 0, g;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
27
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
28 while (*name) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
29 h = (h << 4) + *name++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
30 g = h & 0xf0000000;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
31 if (g)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
32 h ^= g >> 24;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
33 h &= ~g;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
34 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
35 return h;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
36 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
37
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
38 /* rebuild hash table of section s */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
39 /* NOTE: we do factorize the hash table code to go faster */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
40 static void rebuild_hash(Section *s, unsigned int nb_buckets)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
41 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
42 Elf32_Sym *sym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
43 int *ptr, *hash, nb_syms, sym_index, h;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
44 char *strtab;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
45
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
46 strtab = s->link->data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
47 nb_syms = s->data_offset / sizeof(Elf32_Sym);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
48
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
49 s->hash->data_offset = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
50 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
51 ptr[0] = nb_buckets;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
52 ptr[1] = nb_syms;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
53 ptr += 2;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
54 hash = ptr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
55 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
56 ptr += nb_buckets + 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
57
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
58 sym = (Elf32_Sym *)s->data + 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
59 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
60 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
61 h = elf_hash(strtab + sym->st_name) % nb_buckets;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
62 *ptr = hash[h];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
63 hash[h] = sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
64 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
65 *ptr = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
66 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
67 ptr++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
68 sym++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
69 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
70 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
71
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
72 /* return the symbol number */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
73 static int put_elf_sym(Section *s,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
74 unsigned long value, unsigned long size,
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
75 int info, int other, int shndx, char *name)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
76 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
77 int name_offset, sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
78 int nbuckets, h;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
79 Elf32_Sym *sym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
80 Section *hs;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
81
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
82 sym = section_ptr_add(s, sizeof(Elf32_Sym));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
83 if (name)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
84 name_offset = put_elf_str(s->link, name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
85 else
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
86 name_offset = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
87 /* XXX: endianness */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
88 sym->st_name = name_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
89 sym->st_value = value;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
90 sym->st_size = size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
91 sym->st_info = info;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
92 sym->st_other = other;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
93 sym->st_shndx = shndx;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
94 sym_index = sym - (Elf32_Sym *)s->data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
95 hs = s->hash;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
96 if (hs) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
97 int *ptr, *base;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
98 ptr = section_ptr_add(hs, sizeof(int));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
99 base = (int *)hs->data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
100 /* only add global or weak symbols */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
101 if (ELF32_ST_BIND(info) != STB_LOCAL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
102 /* add another hashing entry */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
103 nbuckets = base[0];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
104 h = elf_hash(name) % nbuckets;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
105 *ptr = base[2 + h];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
106 base[2 + h] = sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
107 base[1]++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
108 /* we resize the hash table */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
109 hs->nb_hashed_syms++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
110 if (hs->nb_hashed_syms > 2 * nbuckets) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
111 rebuild_hash(s, 2 * nbuckets);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
112 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
113 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
114 *ptr = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
115 base[1]++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
116 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
117 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
118 return sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
119 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
120
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
121 /* find global ELF symbol 'name' and return its index. Return 0 if not
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
122 found. */
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
123 static int find_elf_sym(Section *s, char *name)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
124 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
125 Elf32_Sym *sym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
126 Section *hs;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
127 int nbuckets, sym_index, h;
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
128 char *name1;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
129
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
130 hs = s->hash;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
131 if (!hs)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
132 return 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
133 nbuckets = ((int *)hs->data)[0];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
134 h = elf_hash(name) % nbuckets;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
135 sym_index = ((int *)hs->data)[2 + h];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
136 while (sym_index != 0) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
137 sym = &((Elf32_Sym *)s->data)[sym_index];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
138 name1 = s->link->data + sym->st_name;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
139 if (!strcmp(name, name1))
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
140 return sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
141 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
142 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
143 return 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
144 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
145
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
146 /* return elf symbol value or error */
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
147 int tcc_get_symbol(TCCState *s, unsigned long *pval, char *name)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
148 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
149 int sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
150 Elf32_Sym *sym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
151
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
152 sym_index = find_elf_sym(symtab_section, name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
153 if (!sym_index)
283
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
154 return -1;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
155 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
283
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
156 *pval = sym->st_value;
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
157 return 0;
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
158 }
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
159
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
160 void *tcc_get_symbol_err(TCCState *s, char *name)
283
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
161 {
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
162 unsigned long val;
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
163 if (tcc_get_symbol(s, &val, name) < 0)
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
164 error("%s not defined", name);
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
165 return (void *)val;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
166 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
167
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
168 /* add an elf symbol : check if it is already defined and patch
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
169 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
170 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
171 int info, int other, int sh_num, char *name)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
172 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
173 Elf32_Sym *esym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
174 int sym_bind, sym_index, sym_type, esym_bind;
469
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
175 unsigned char sym_vis, esym_vis, new_vis;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
176
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
177 sym_bind = ELF32_ST_BIND(info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
178 sym_type = ELF32_ST_TYPE(info);
469
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
179 sym_vis = ELF32_ST_VISIBILITY(other);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
180
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
181 if (sym_bind != STB_LOCAL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
182 /* we search global or weak symbols */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
183 sym_index = find_elf_sym(s, name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
184 if (!sym_index)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
185 goto do_def;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
186 esym = &((Elf32_Sym *)s->data)[sym_index];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
187 if (esym->st_shndx != SHN_UNDEF) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
188 esym_bind = ELF32_ST_BIND(esym->st_info);
469
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
189 /* propagate the most constraining visibility */
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
190 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
191 esym_vis = ELF32_ST_VISIBILITY(esym->st_other);
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
192 if (esym_vis == STV_DEFAULT) {
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
193 new_vis = sym_vis;
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
194 } else if (sym_vis == STV_DEFAULT) {
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
195 new_vis = esym_vis;
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
196 } else {
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
197 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
198 }
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
199 esym->st_other = (esym->st_other & ~ELF32_ST_VISIBILITY(UCHAR_MAX))
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
200 | new_vis;
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
201 other = esym->st_other; /* in case we have to patch esym */
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
202 if (sh_num == SHN_UNDEF) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
203 /* ignore adding of undefined symbol if the
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
204 corresponding symbol is already defined */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
205 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
206 /* global overrides weak, so patch */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
207 goto do_patch;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
208 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
209 /* weak is ignored if already global */
469
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
210 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
bb13836ab658 Patch from Vincent Pit to fix visibility problems in the linker (resulting
Rob Landley <rob@landley.net>
parents: 409
diff changeset
211 /* ignore hidden symbols after */
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
212 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
213 #if 0
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
214 printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
215 sym_bind, sh_num, esym_bind, esym->st_shndx);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
216 #endif
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
217 /* NOTE: we accept that two DLL define the same symbol */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
218 if (s != tcc_state->dynsymtab_section)
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
219 error_noabort("'%s' defined twice", name);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
220 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
221 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
222 do_patch:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
223 esym->st_info = ELF32_ST_INFO(sym_bind, sym_type);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
224 esym->st_shndx = sh_num;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
225 esym->st_value = value;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
226 esym->st_size = size;
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
227 esym->st_other = other;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
228 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
229 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
230 do_def:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
231 sym_index = put_elf_sym(s, value, size,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
232 ELF32_ST_INFO(sym_bind, sym_type), other,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
233 sh_num, name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
234 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
235 return sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
236 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
237
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
238 /* put relocation */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
239 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
240 int type, int symbol)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
241 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
242 char buf[256];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
243 Section *sr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
244 Elf32_Rel *rel;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
245
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
246 sr = s->reloc;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
247 if (!sr) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
248 /* if no relocation section, create it */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
249 snprintf(buf, sizeof(buf), ".rel%s", s->name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
250 /* if the symtab is allocated, then we consider the relocation
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
251 are also */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
252 sr = new_section(tcc_state, buf, SHT_REL, symtab->sh_flags);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
253 sr->sh_entsize = sizeof(Elf32_Rel);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
254 sr->link = symtab;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
255 sr->sh_info = s->sh_num;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
256 s->reloc = sr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
257 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
258 rel = section_ptr_add(sr, sizeof(Elf32_Rel));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
259 rel->r_offset = offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
260 rel->r_info = ELF32_R_INFO(symbol, type);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
261 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
262
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
263 /* put stab debug information */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
264
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
265 typedef struct {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
266 unsigned long n_strx; /* index into string table of name */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
267 unsigned char n_type; /* type of symbol */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
268 unsigned char n_other; /* misc info (usually empty) */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
269 unsigned short n_desc; /* description field */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
270 unsigned long n_value; /* value of symbol */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
271 } Stab_Sym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
272
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
273 static void put_stabs(char *str, int type, int other, int desc,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
274 unsigned long value)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
275 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
276 Stab_Sym *sym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
277
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
278 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
279 if (str) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
280 sym->n_strx = put_elf_str(stabstr_section, str);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
281 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
282 sym->n_strx = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
283 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
284 sym->n_type = type;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
285 sym->n_other = other;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
286 sym->n_desc = desc;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
287 sym->n_value = value;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
288 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
289
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
290 static void put_stabs_r(char *str, int type, int other, int desc,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
291 unsigned long value, Section *sec, int sym_index)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
292 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
293 put_stabs(str, type, other, desc, value);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
294 put_elf_reloc(symtab_section, stab_section,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
295 stab_section->data_offset - sizeof(unsigned long),
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
296 R_DATA_32, sym_index);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
297 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
298
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
299 static void put_stabn(int type, int other, int desc, int value)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
300 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
301 put_stabs(NULL, type, other, desc, value);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
302 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
303
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
304 static void put_stabd(int type, int other, int desc)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
305 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
306 put_stabs(NULL, type, other, desc, 0);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
307 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
308
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
309 /* In an ELF file symbol table, the local symbols must appear below
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
310 the global and weak ones. Since TCC cannot sort it while generating
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
311 the code, we must do it after. All the relocation tables are also
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
312 modified to take into account the symbol table sorting */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
313 static void sort_syms(TCCState *s1, Section *s)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
314 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
315 int *old_to_new_syms;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
316 Elf32_Sym *new_syms;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
317 int nb_syms, i;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
318 Elf32_Sym *p, *q;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
319 Elf32_Rel *rel, *rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
320 Section *sr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
321 int type, sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
322
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
323 nb_syms = s->data_offset / sizeof(Elf32_Sym);
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
324 new_syms = xmalloc(nb_syms * sizeof(Elf32_Sym));
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
325 old_to_new_syms = xmalloc(nb_syms * sizeof(int));
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
326
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
327 /* first pass for local symbols */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
328 p = (Elf32_Sym *)s->data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
329 q = new_syms;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
330 for(i = 0; i < nb_syms; i++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
331 if (ELF32_ST_BIND(p->st_info) == STB_LOCAL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
332 old_to_new_syms[i] = q - new_syms;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
333 *q++ = *p;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
334 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
335 p++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
336 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
337 /* save the number of local symbols in section header */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
338 s->sh_info = q - new_syms;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
339
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
340 /* then second pass for non local symbols */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
341 p = (Elf32_Sym *)s->data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
342 for(i = 0; i < nb_syms; i++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
343 if (ELF32_ST_BIND(p->st_info) != STB_LOCAL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
344 old_to_new_syms[i] = q - new_syms;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
345 *q++ = *p;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
346 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
347 p++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
348 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
349
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
350 /* we copy the new symbols to the old */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
351 memcpy(s->data, new_syms, nb_syms * sizeof(Elf32_Sym));
481
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
352 free(new_syms);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
353
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
354 /* now we modify all the relocations */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
355 for(i = 1; i < s1->nb_sections; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
356 sr = s1->sections[i];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
357 if (sr->sh_type == SHT_REL && sr->link == s) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
358 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
359 for(rel = (Elf32_Rel *)sr->data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
360 rel < rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
361 rel++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
362 sym_index = ELF32_R_SYM(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
363 type = ELF32_R_TYPE(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
364 sym_index = old_to_new_syms[sym_index];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
365 rel->r_info = ELF32_R_INFO(sym_index, type);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
366 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
367 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
368 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
369
481
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
370 free(old_to_new_syms);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
371 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
372
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
373 /* relocate common symbols in the .bss section */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
374 static void relocate_common_syms(void)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
375 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
376 Elf32_Sym *sym, *sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
377 unsigned long offset, align;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
378
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
379 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
380 for(sym = (Elf32_Sym *)symtab_section->data + 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
381 sym < sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
382 sym++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
383 if (sym->st_shndx == SHN_COMMON) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
384 /* align symbol */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
385 align = sym->st_value;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
386 offset = bss_section->data_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
387 offset = (offset + align - 1) & -align;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
388 sym->st_value = offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
389 sym->st_shndx = bss_section->sh_num;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
390 offset += sym->st_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
391 bss_section->data_offset = offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
392 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
393 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
394 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
395
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
396 /* relocate symbol table, resolve undefined symbols if do_resolve is
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
397 true and output error if undefined symbol. */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
398 static void relocate_syms(TCCState *s1, int do_resolve)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
399 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
400 Elf32_Sym *sym, *esym, *sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
401 int sym_bind, sh_num, sym_index;
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
402 char *name;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
403 unsigned long addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
404
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
405 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
406 for(sym = (Elf32_Sym *)symtab_section->data + 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
407 sym < sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
408 sym++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
409 sh_num = sym->st_shndx;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
410 if (sh_num == SHN_UNDEF) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
411 name = strtab_section->data + sym->st_name;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
412 if (do_resolve) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
413 name = symtab_section->link->data + sym->st_name;
350
4ebba89e2599 [project @ 2005-04-10 21:46:58 by bellard]
bellard
parents: 342
diff changeset
414 addr = (unsigned long)resolve_sym(s1, name, ELF32_ST_TYPE(sym->st_info));
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
415 if (addr) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
416 sym->st_value = addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
417 goto found;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
418 }
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
419 } else if (s1->dynsym) {
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
420 /* if dynamic symbol exist, then use it */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
421 sym_index = find_elf_sym(s1->dynsym, name);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
422 if (sym_index) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
423 esym = &((Elf32_Sym *)s1->dynsym->data)[sym_index];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
424 sym->st_value = esym->st_value;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
425 goto found;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
426 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
427 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
428 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
429 it */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
430 if (!strcmp(name, "_fp_hw"))
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
431 goto found;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
432 /* only weak symbols are accepted to be undefined. Their
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
433 value is zero */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
434 sym_bind = ELF32_ST_BIND(sym->st_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
435 if (sym_bind == STB_WEAK) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
436 sym->st_value = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
437 } else {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
438 error_noabort("undefined symbol '%s'", name);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
439 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
440 } else if (sh_num < SHN_LORESERVE) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
441 /* add section base */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
442 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
443 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
444 found: ;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
445 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
446 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
447
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
448 /* relocate a given section (CPU dependent) */
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
449 static void relocate_section(TCCState *s1, Section *s)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
450 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
451 Section *sr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
452 Elf32_Rel *rel, *rel_end, *qrel;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
453 Elf32_Sym *sym;
342
5200ac599ebd [project @ 2004-11-07 15:45:52 by bellard]
bellard
parents: 331
diff changeset
454 int type, sym_index;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
455 unsigned char *ptr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
456 unsigned long val, addr;
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
457 #if defined(TINYCC_TARGET_I386)
342
5200ac599ebd [project @ 2004-11-07 15:45:52 by bellard]
bellard
parents: 331
diff changeset
458 int esym_index;
5200ac599ebd [project @ 2004-11-07 15:45:52 by bellard]
bellard
parents: 331
diff changeset
459 #endif
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
460
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
461 sr = s->reloc;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
462 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
463 qrel = (Elf32_Rel *)sr->data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
464 for(rel = qrel;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
465 rel < rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
466 rel++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
467 ptr = s->data + rel->r_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
468
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
469 sym_index = ELF32_R_SYM(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
470 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
471 val = sym->st_value;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
472 type = ELF32_R_TYPE(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
473 addr = s->sh_addr + rel->r_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
474
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
475 /* CPU specific */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
476 switch(type) {
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
477 #if defined(TINYCC_TARGET_I386)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
478 case R_386_32:
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
479 if (tccg_output_type == TCC_OUTPUT_DLL) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
480 esym_index = s1->symtab_to_dynsym[sym_index];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
481 qrel->r_offset = rel->r_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
482 if (esym_index) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
483 qrel->r_info = ELF32_R_INFO(esym_index, R_386_32);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
484 qrel++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
485 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
486 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
487 qrel->r_info = ELF32_R_INFO(0, R_386_RELATIVE);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
488 qrel++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
489 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
490 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
491 *(int *)ptr += val;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
492 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
493 case R_386_PC32:
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
494 if (tccg_output_type == TCC_OUTPUT_DLL) {
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
495 /* DLL relocation */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
496 esym_index = s1->symtab_to_dynsym[sym_index];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
497 if (esym_index) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
498 qrel->r_offset = rel->r_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
499 qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
500 qrel++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
501 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
502 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
503 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
504 *(int *)ptr += val - addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
505 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
506 case R_386_PLT32:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
507 *(int *)ptr += val - addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
508 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
509 case R_386_GLOB_DAT:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
510 case R_386_JMP_SLOT:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
511 *(int *)ptr = val;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
512 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
513 case R_386_GOTPC:
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
514 *(int *)ptr += s1->got->sh_addr - addr;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
515 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
516 case R_386_GOTOFF:
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
517 *(int *)ptr += val - s1->got->sh_addr;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
518 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
519 case R_386_GOT32:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
520 /* we load the got offset */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
521 *(int *)ptr += s1->got_offsets[sym_index];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
522 break;
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
523 #elif defined(TINYCC_TARGET_ARM)
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
524 case R_ARM_PC24:
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
525 case R_ARM_CALL:
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
526 case R_ARM_JUMP24:
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
527 case R_ARM_PLT32:
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
528 {
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
529 int x;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
530 x = (*(int *)ptr)&0xffffff;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
531 (*(int *)ptr) &= 0xff000000;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
532 if (x & 0x800000)
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
533 x -= 0x1000000;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
534 x *= 4;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
535 x += val - addr;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
536 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
537 error("can't relocate value at %x",addr);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
538 x >>= 2;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
539 x &= 0xffffff;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
540 (*(int *)ptr) |= x;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
541 }
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
542 break;
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
543 case R_ARM_PREL31:
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
544 {
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
545 int x;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
546 x = (*(int *)ptr) & 0x7fffffff;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
547 (*(int *)ptr) &= 0x80000000;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
548 x = (x * 2) / 2;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
549 x += val - addr;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
550 if((x^(x>>1))&0x40000000)
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
551 error("can't relocate value at %x",addr);
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
552 (*(int *)ptr) |= x & 0x7fffffff;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
553 }
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
554 case R_ARM_ABS32:
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
555 *(int *)ptr += val;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
556 break;
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
557 case R_ARM_BASE_PREL:
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
558 *(int *)ptr += s1->got->sh_addr - addr;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
559 break;
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
560 case R_ARM_GOTOFF32:
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
561 *(int *)ptr += val - s1->got->sh_addr;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
562 break;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
563 case R_ARM_GOT_BREL:
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
564 /* we load the got offset */
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
565 *(int *)ptr += s1->got_offsets[sym_index];
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
566 break;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
567 case R_ARM_COPY:
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
568 break;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
569 default:
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
570 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
571 type,addr,(unsigned int )ptr,val);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
572 break;
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
573 #elif defined(TINYCC_TARGET_C67)
305
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
574 case R_C60_32:
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
575 *(int *)ptr += val;
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
576 break;
309
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
577 case R_C60LO16:
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
578 {
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
579 uint32_t orig;
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
580
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
581 /* put the low 16 bits of the absolute address */
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
582 // add to what is already there
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
583
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
584 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
585 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
586
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
587 //patch both at once - assumes always in pairs Low - High
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
588
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
589 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
590 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
591 }
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
592 break;
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
593 case R_C60HI16:
5447291470b8 [project @ 2004-10-05 22:33:55 by bellard]
bellard
parents: 305
diff changeset
594 break;
305
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
595 default:
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
596 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
597 type,addr,(unsigned int )ptr,val);
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
598 break;
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
599 #else
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
600 #error unsupported processor
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
601 #endif
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
602 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
603 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
604 /* if the relocation is allocated, we change its symbol table */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
605 if (sr->sh_flags & SHF_ALLOC)
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
606 sr->link = s1->dynsym;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
607 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
608
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
609 /* relocate relocation table in 'sr' */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
610 static void relocate_rel(TCCState *s1, Section *sr)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
611 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
612 Section *s;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
613 Elf32_Rel *rel, *rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
614
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
615 s = s1->sections[sr->sh_info];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
616 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
617 for(rel = (Elf32_Rel *)sr->data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
618 rel < rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
619 rel++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
620 rel->r_offset += s->sh_addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
621 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
622 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
623
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
624 /* count the number of dynamic relocations so that we can reserve
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
625 their space */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
626 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
627 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
628 Elf32_Rel *rel, *rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
629 int sym_index, esym_index, type, count;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
630
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
631 count = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
632 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
633 for(rel = (Elf32_Rel *)sr->data; rel < rel_end; rel++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
634 sym_index = ELF32_R_SYM(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
635 type = ELF32_R_TYPE(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
636 switch(type) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
637 case R_386_32:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
638 count++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
639 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
640 case R_386_PC32:
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
641 esym_index = s1->symtab_to_dynsym[sym_index];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
642 if (esym_index)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
643 count++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
644 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
645 default:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
646 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
647 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
648 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
649 if (count) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
650 /* allocate the section */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
651 sr->sh_flags |= SHF_ALLOC;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
652 sr->sh_size = count * sizeof(Elf32_Rel);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
653 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
654 return count;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
655 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
656
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
657 static void put_got_offset(TCCState *s1, int index, unsigned long val)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
658 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
659 int n;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
660 unsigned long *tab;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
661
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
662 if (index >= s1->nb_got_offsets) {
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
663 /* find immediately bigger power of 2 and reallocate array */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
664 n = 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
665 while (index >= n)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
666 n *= 2;
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
667 tab = xrealloc(s1->got_offsets, n * sizeof(unsigned long));
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
668 s1->got_offsets = tab;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
669 memset(s1->got_offsets + s1->nb_got_offsets, 0,
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
670 (n - s1->nb_got_offsets) * sizeof(unsigned long));
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
671 s1->nb_got_offsets = n;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
672 }
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
673 s1->got_offsets[index] = val;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
674 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
675
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
676 /* XXX: suppress that */
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
677 static void put32(unsigned char *p, uint32_t val)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
678 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
679 p[0] = val;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
680 p[1] = val >> 8;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
681 p[2] = val >> 16;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
682 p[3] = val >> 24;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
683 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
684
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
685 #if defined(TINYCC_TARGET_I386) || defined(TINYCC_TARGET_ARM)
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
686 static uint32_t get32(unsigned char *p)
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
687 {
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
688 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
689 }
342
5200ac599ebd [project @ 2004-11-07 15:45:52 by bellard]
bellard
parents: 331
diff changeset
690 #endif
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
691
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
692 static void build_got(TCCState *s1)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
693 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
694 unsigned char *ptr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
695
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
696 /* if no got, then create it */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
697 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
698 s1->got->sh_entsize = 4;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
699 add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
700 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
701 ptr = section_ptr_add(s1->got, 3 * sizeof(int));
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
702 /* keep space for _DYNAMIC pointer, if present */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
703 put32(ptr, 0);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
704 /* two dummy got entries */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
705 put32(ptr + 4, 0);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
706 put32(ptr + 8, 0);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
707 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
708
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
709 /* put a got entry corresponding to a symbol in symtab_section. 'size'
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
710 and 'info' can be modifed if more precise info comes from the DLL */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
711 static void put_got_entry(TCCState *s1,
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
712 int reloc_type, unsigned long size, int info,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
713 int sym_index)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
714 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
715 int index;
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
716 char *name;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
717 Elf32_Sym *sym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
718 unsigned long offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
719 int *ptr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
720
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
721 if (!s1->got)
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
722 build_got(s1);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
723
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
724 /* if a got entry already exists for that symbol, no need to add one */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
725 if (sym_index < s1->nb_got_offsets &&
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
726 s1->got_offsets[sym_index] != 0)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
727 return;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
728
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
729 put_got_offset(s1, sym_index, s1->got->data_offset);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
730
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
731 if (s1->dynsym) {
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
732 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
733 name = symtab_section->link->data + sym->st_name;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
734 offset = sym->st_value;
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
735 #ifdef TINYCC_TARGET_I386
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
736 if (reloc_type == R_386_JMP_SLOT) {
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
737 Section *plt;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
738 uint8_t *p;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
739 int modrm;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
740
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
741 /* if we build a DLL, we add a %ebx offset */
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
742 if (tccg_output_type == TCC_OUTPUT_DLL)
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
743 modrm = 0xa3;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
744 else
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
745 modrm = 0x25;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
746
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
747 /* add a PLT entry */
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
748 plt = s1->plt;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
749 if (plt->data_offset == 0) {
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
750 /* first plt entry */
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
751 p = section_ptr_add(plt, 16);
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
752 p[0] = 0xff; /* pushl got + 4 */
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
753 p[1] = modrm + 0x10;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
754 put32(p + 2, 4);
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
755 p[6] = 0xff; /* jmp *(got + 8) */
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
756 p[7] = modrm;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
757 put32(p + 8, 8);
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
758 }
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
759
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
760 p = section_ptr_add(plt, 16);
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
761 p[0] = 0xff; /* jmp *(got + x) */
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
762 p[1] = modrm;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
763 put32(p + 2, s1->got->data_offset);
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
764 p[6] = 0x68; /* push $xxx */
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
765 put32(p + 7, (plt->data_offset - 32) >> 1);
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
766 p[11] = 0xe9; /* jmp plt_start */
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
767 put32(p + 12, -(plt->data_offset));
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
768
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
769 /* the symbol is modified so that it will be relocated to
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
770 the PLT */
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
771 if (tccg_output_type == TCC_OUTPUT_EXE)
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
772 offset = plt->data_offset - 16;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
773 }
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
774 #elif defined(TINYCC_TARGET_ARM)
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
775 if (reloc_type == R_ARM_JUMP_SLOT) {
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
776 Section *plt;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
777 uint8_t *p;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
778
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
779 /* if we build a DLL, we add a %ebx offset */
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
780 if (tccg_output_type == TCC_OUTPUT_DLL)
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
781 error("DLLs unimplemented!");
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
782
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
783 /* add a PLT entry */
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
784 plt = s1->plt;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
785 if (plt->data_offset == 0) {
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
786 /* first plt entry */
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
787 p = section_ptr_add(plt, 16);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
788 put32(p , 0xe52de004);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
789 put32(p + 4, 0xe59fe010);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
790 put32(p + 8, 0xe08fe00e);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
791 put32(p + 12, 0xe5bef008);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
792 }
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
793
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
794 p = section_ptr_add(plt, 16);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
795 put32(p , 0xe59fc004);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
796 put32(p+4, 0xe08fc00c);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
797 put32(p+8, 0xe59cf000);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
798 put32(p+12, s1->got->data_offset);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
799
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
800 /* the symbol is modified so that it will be relocated to
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
801 the PLT */
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
802 if (tccg_output_type == TCC_OUTPUT_EXE)
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
803 offset = plt->data_offset - 16;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
804 }
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
805 #elif defined(TINYCC_TARGET_C67)
305
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
806 error("C67 got not implemented");
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
807 #else
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
808 #error unsupported CPU
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
809 #endif
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
810 index = put_elf_sym(s1->dynsym, offset,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
811 size, info, 0, sym->st_shndx, name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
812 /* put a got entry */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
813 put_elf_reloc(s1->dynsym, s1->got,
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
814 s1->got->data_offset,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
815 reloc_type, index);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
816 }
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
817 ptr = section_ptr_add(s1->got, sizeof(int));
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
818 *ptr = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
819 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
820
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
821 /* build GOT and PLT entries */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
822 static void build_got_entries(TCCState *s1)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
823 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
824 Section *s, *symtab;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
825 Elf32_Rel *rel, *rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
826 Elf32_Sym *sym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
827 int i, type, reloc_type, sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
828
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
829 for(i = 1; i < s1->nb_sections; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
830 s = s1->sections[i];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
831 if (s->sh_type != SHT_REL)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
832 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
833 /* no need to handle got relocations */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
834 if (s->link != symtab_section)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
835 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
836 symtab = s->link;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
837 rel_end = (Elf32_Rel *)(s->data + s->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
838 for(rel = (Elf32_Rel *)s->data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
839 rel < rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
840 rel++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
841 type = ELF32_R_TYPE(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
842 switch(type) {
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
843 #if defined(TINYCC_TARGET_I386)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
844 case R_386_GOT32:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
845 case R_386_GOTOFF:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
846 case R_386_GOTPC:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
847 case R_386_PLT32:
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
848 if (!s1->got)
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
849 build_got(s1);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
850 if (type == R_386_GOT32 || type == R_386_PLT32) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
851 sym_index = ELF32_R_SYM(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
852 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
853 /* look at the symbol got offset. If none, then add one */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
854 if (type == R_386_GOT32)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
855 reloc_type = R_386_GLOB_DAT;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
856 else
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
857 reloc_type = R_386_JMP_SLOT;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
858 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
859 sym_index);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
860 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
861 break;
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
862 #elif defined(TINYCC_TARGET_ARM)
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
863 case R_ARM_GOT_BREL:
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
864 case R_ARM_GOTOFF32:
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
865 case R_ARM_BASE_PREL:
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
866 case R_ARM_PLT32:
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
867 if (!s1->got)
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
868 build_got(s1);
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
869 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
870 sym_index = ELF32_R_SYM(rel->r_info);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
871 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
872 /* look at the symbol got offset. If none, then add one */
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
873 if (type == R_ARM_GOT_BREL)
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
874 reloc_type = R_ARM_GLOB_DAT;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
875 else
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
876 reloc_type = R_ARM_JUMP_SLOT;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
877 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
878 sym_index);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
879 }
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
880 break;
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
881 #elif defined(TINYCC_TARGET_C67)
305
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
882 case R_C60_GOT32:
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
883 case R_C60_GOTOFF:
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
884 case R_C60_GOTPC:
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
885 case R_C60_PLT32:
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
886 if (!s1->got)
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
887 build_got(s1);
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
888 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
889 sym_index = ELF32_R_SYM(rel->r_info);
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
890 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
891 /* look at the symbol got offset. If none, then add one */
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
892 if (type == R_C60_GOT32)
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
893 reloc_type = R_C60_GLOB_DAT;
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
894 else
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
895 reloc_type = R_C60_JMP_SLOT;
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
896 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
897 sym_index);
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
898 }
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
899 break;
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
900 #else
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
901 #error unsupported CPU
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
902 #endif
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
903 default:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
904 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
905 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
906 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
907 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
908 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
909
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
910 static Section *new_symtab(TCCState *s1,
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
911 char *symtab_name, int sh_type, int sh_flags,
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
912 char *strtab_name,
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
913 char *hash_name, int hash_sh_flags)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
914 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
915 Section *symtab, *strtab, *hash;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
916 int *ptr, nb_buckets;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
917
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
918 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
919 symtab->sh_entsize = sizeof(Elf32_Sym);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
920 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
921 put_elf_str(strtab, "");
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
922 symtab->link = strtab;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
923 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
924
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
925 nb_buckets = 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
926
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
927 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
928 hash->sh_entsize = sizeof(int);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
929 symtab->hash = hash;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
930 hash->link = symtab;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
931
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
932 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
933 ptr[0] = nb_buckets;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
934 ptr[1] = 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
935 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
936 return symtab;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
937 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
938
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
939 /* put dynamic tag */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
940 static void put_dt(Section *dynamic, int dt, unsigned long val)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
941 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
942 Elf32_Dyn *dyn;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
943 dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
944 dyn->d_tag = dt;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
945 dyn->d_un.d_val = val;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
946 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
947
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
948 static void add_init_array_defines(TCCState *s1, char *section_name)
278
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
949 {
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
950 Section *s;
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
951 long end_offset;
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
952 char sym_start[1024];
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
953 char sym_end[1024];
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
954
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
955 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
956 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
957
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
958 s = find_section(s1, section_name);
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
959 if (!s) {
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
960 end_offset = 0;
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
961 s = data_section;
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
962 } else {
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
963 end_offset = s->data_offset;
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
964 }
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
965
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
966 add_elf_sym(symtab_section,
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
967 0, 0,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
968 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
278
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
969 s->sh_num, sym_start);
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
970 add_elf_sym(symtab_section,
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
971 end_offset, 0,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
972 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
278
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
973 s->sh_num, sym_end);
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
974 }
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
975
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
976 /* add tcc runtime libraries */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
977 static void tcc_add_runtime(TCCState *s1)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
978 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
979 char buf[1024];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
980
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
981 #ifdef CONFIG_TCC_BCHECK
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
982 if (do_bounds_check) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
983 unsigned long *ptr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
984 Section *init_section;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
985 unsigned char *pinit;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
986 int sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
987
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
988 /* XXX: add an object file to do that */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
989 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
990 *ptr = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
991 add_elf_sym(symtab_section, 0, 0,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
992 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
993 bounds_section->sh_num, "__bounds_start");
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
994 /* add bound check code */
522
a6abef04cb53 Fix path logic so "hello world" builds again. (Still need to finish install.)
Rob Landley <rob@landley.net>
parents: 519
diff changeset
995 snprintf(buf, sizeof(buf), "%s/bcheck.o", tinycc_path);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
996 tcc_add_file(s1, buf);
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
997 #ifdef TINYCC_TARGET_I386
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
998 if (tccg_output_type != TCC_OUTPUT_MEMORY) {
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
999 /* add 'call __bound_init()' in .init section */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1000 init_section = find_section(s1, ".init");
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1001 pinit = section_ptr_add(init_section, 5);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1002 pinit[0] = 0xe8;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1003 put32(pinit + 1, -4);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1004 sym_index = find_elf_sym(symtab_section, "__bound_init");
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1005 put_elf_reloc(symtab_section, init_section,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1006 init_section->data_offset - 4, R_386_PC32, sym_index);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1007 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1008 #endif
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1009 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1010 #endif
511
374af493d0ac More work on the library paths so we can override enough things to build
Rob Landley <rob@landley.net>
parents: 507
diff changeset
1011 // add libc
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1012 if (!tccg_nostdlib) {
289
4df05eda3e3f [project @ 2003-10-04 21:24:46 by bellard]
bellard
parents: 287
diff changeset
1013 tcc_add_library(s1, "c");
547
9778e985b450 Rename runtime library to libtinyccrt-$ARCH.a, build libtinycc-$ARCH.so to
Rob Landley <rob@landley.net>
parents: 529
diff changeset
1014 tcc_add_library(s1, "tinyccrt-" TINYCC_TARGET);
511
374af493d0ac More work on the library paths so we can override enough things to build
Rob Landley <rob@landley.net>
parents: 507
diff changeset
1015 // add crt end if not memory output
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1016 if (tccg_output_type != TCC_OUTPUT_MEMORY)
564
d89a6822b7e0 Use library search path for crt?.o, and for ld script libraries with no path.
Rob Landley <rob@landley.net>
parents: 555
diff changeset
1017 tcc_add_dll(s1, "crtn.o", AFF_PRINT_ERROR);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1018 }
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1019 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1020
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1021 /* add various standard linker symbols (must be done after the
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1022 sections are filled (for example after allocating common
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1023 symbols)) */
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1024 static void tcc_add_linker_symbols(TCCState *s1)
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1025 {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1026 char buf[1024];
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1027 int i;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1028 Section *s;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1029
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1030 add_elf_sym(symtab_section,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1031 text_section->data_offset, 0,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
1032 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1033 text_section->sh_num, "_etext");
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1034 add_elf_sym(symtab_section,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1035 data_section->data_offset, 0,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
1036 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1037 data_section->sh_num, "_edata");
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1038 add_elf_sym(symtab_section,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1039 bss_section->data_offset, 0,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
1040 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1041 bss_section->sh_num, "_end");
278
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
1042 /* horrible new standard ldscript defines */
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
1043 add_init_array_defines(s1, ".preinit_array");
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
1044 add_init_array_defines(s1, ".init_array");
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
1045 add_init_array_defines(s1, ".fini_array");
b3dcb3c54671 [project @ 2003-05-29 22:52:53 by bellard]
bellard
parents: 272
diff changeset
1046
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1047 /* add start and stop symbols for sections whose name can be
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1048 expressed in C */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1049 for(i = 1; i < s1->nb_sections; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1050 s = s1->sections[i];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1051 if (s->sh_type == SHT_PROGBITS &&
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1052 (s->sh_flags & SHF_ALLOC)) {
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
1053 char *p;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1054 int ch;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1055
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1056 /* check if section name can be expressed in C */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1057 p = s->name;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1058 for(;;) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1059 ch = *p;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1060 if (!ch)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1061 break;
505
9311fc3f8e39 Every use of isid() can be replaced by isidnum_table[], so do it.
Rob Landley <rob@landley.net>
parents: 503
diff changeset
1062 if (!isidnum_table[ch])
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1063 goto next_sec;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1064 p++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1065 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1066 snprintf(buf, sizeof(buf), "__start_%s", s->name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1067 add_elf_sym(symtab_section,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1068 0, 0,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
1069 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1070 s->sh_num, buf);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1071 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1072 add_elf_sym(symtab_section,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1073 s->data_offset, 0,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
1074 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1075 s->sh_num, buf);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1076 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1077 next_sec: ;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1078 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1079 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1080
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1081 /* name of ELF interpreter */
570
c42c2145d359 The dynamic linker location belongs in configure, move it there.
Rob Landley <rob@landley.net>
parents: 564
diff changeset
1082 static char elf_interp[] = CC_DYNAMIC_LINKER;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1083
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1084 static void tcc_output_binary(TCCState *s1, FILE *f,
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
1085 int *section_order)
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1086 {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1087 Section *s;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1088 int i, offset, size;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1089
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1090 offset = 0;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1091 for(i=1;i<s1->nb_sections;i++) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1092 s = s1->sections[section_order[i]];
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1093 if (s->sh_type != SHT_NOBITS &&
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1094 (s->sh_flags & SHF_ALLOC)) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1095 while (offset < s->sh_offset) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1096 fputc(0, f);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1097 offset++;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1098 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1099 size = s->sh_size;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1100 fwrite(s->data, 1, size, f);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1101 offset += size;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1102 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1103 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1104 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1105
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1106 /* output an ELF file */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1107 /* XXX: suppress unneeded sections */
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
1108 int tcc_output_file(TCCState *s1, char *filename)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1109 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1110 Elf32_Ehdr ehdr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1111 FILE *f;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1112 int fd, mode, ret;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1113 int *section_order;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1114 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1115 unsigned long addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1116 Section *strsec, *s;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1117 Elf32_Shdr shdr, *sh;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1118 Elf32_Phdr *phdr, *ph;
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1119 Section *interp, *dynamic, *dynstr;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1120 unsigned long saved_dynamic_data_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1121 Elf32_Sym *sym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1122 int type, file_type;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1123 unsigned long rel_addr, rel_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1124
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1125 file_type = tccg_output_type;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1126 s1->nb_errors = 0;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1127
319
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1128 if (file_type != TCC_OUTPUT_OBJ) {
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1129 tcc_add_runtime(s1);
319
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1130 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1131
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1132 phdr = NULL;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1133 section_order = NULL;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1134 interp = NULL;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1135 dynamic = NULL;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1136 dynstr = NULL; /* avoid warning */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1137 saved_dynamic_data_offset = 0; /* avoid warning */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1138
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1139 if (file_type != TCC_OUTPUT_OBJ) {
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1140 relocate_common_syms();
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1141
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1142 tcc_add_linker_symbols(s1);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1143
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1144 if (!tccg_static_link) {
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
1145 char *name;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1146 int sym_index, index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1147 Elf32_Sym *esym, *sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1148
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1149 if (file_type == TCC_OUTPUT_EXE) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1150 char *ptr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1151 /* add interpreter section only if executable */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1152 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1153 interp->sh_addralign = 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1154 ptr = section_ptr_add(interp, sizeof(elf_interp));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1155 strcpy(ptr, elf_interp);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1156 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1157
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1158 /* add dynamic symbol table */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1159 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1160 ".dynstr",
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1161 ".hash", SHF_ALLOC);
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1162 dynstr = s1->dynsym->link;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1163
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1164 /* add dynamic section */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1165 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1166 SHF_ALLOC | SHF_WRITE);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1167 dynamic->link = dynstr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1168 dynamic->sh_entsize = sizeof(Elf32_Dyn);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1169
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1170 /* add PLT */
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1171 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1172 SHF_ALLOC | SHF_EXECINSTR);
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1173 s1->plt->sh_entsize = 4;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1174
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1175 build_got(s1);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1176
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1177 /* scan for undefined symbols and see if they are in the
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1178 dynamic symbols. If a symbol STT_FUNC is found, then we
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1179 add it in the PLT. If a symbol STT_OBJECT is found, we
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1180 add it in the .bss section with a suitable relocation */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1181 sym_end = (Elf32_Sym *)(symtab_section->data +
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1182 symtab_section->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1183 if (file_type == TCC_OUTPUT_EXE) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1184 for(sym = (Elf32_Sym *)symtab_section->data + 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1185 sym < sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1186 sym++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1187 if (sym->st_shndx == SHN_UNDEF) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1188 name = symtab_section->link->data + sym->st_name;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1189 sym_index = find_elf_sym(s1->dynsymtab_section, name);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1190 if (sym_index) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1191 esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1192 type = ELF32_ST_TYPE(esym->st_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1193 if (type == STT_FUNC) {
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1194 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1195 esym->st_info,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1196 sym - (Elf32_Sym *)symtab_section->data);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1197 } else if (type == STT_OBJECT) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1198 unsigned long offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1199 offset = bss_section->data_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1200 /* XXX: which alignment ? */
272
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1201 offset = (offset + 16 - 1) & -16;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1202 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1203 esym->st_info, 0,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1204 bss_section->sh_num, name);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1205 put_elf_reloc(s1->dynsym, bss_section,
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1206 offset, R_COPY, index);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1207 offset += esym->st_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1208 bss_section->data_offset = offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1209 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1210 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1211 /* STB_WEAK undefined symbols are accepted */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1212 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1213 it */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1214 if (ELF32_ST_BIND(sym->st_info) == STB_WEAK ||
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1215 !strcmp(name, "_fp_hw")) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1216 } else {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1217 error_noabort("undefined symbol '%s'", name);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1218 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1219 }
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1220 } else if (tccg_rdynamic &&
272
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1221 ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1222 /* if -rdynamic option, then export all non
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1223 local symbols */
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1224 name = symtab_section->link->data + sym->st_name;
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1225 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1226 sym->st_info, 0,
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1227 sym->st_shndx, name);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1228 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1229 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1230
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1231 if (s1->nb_errors)
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1232 goto fail;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1233
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1234 /* now look at unresolved dynamic symbols and export
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1235 corresponding symbol */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1236 sym_end = (Elf32_Sym *)(s1->dynsymtab_section->data +
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1237 s1->dynsymtab_section->data_offset);
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1238 for(esym = (Elf32_Sym *)s1->dynsymtab_section->data + 1;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1239 esym < sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1240 esym++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1241 if (esym->st_shndx == SHN_UNDEF) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1242 name = s1->dynsymtab_section->link->data + esym->st_name;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1243 sym_index = find_elf_sym(symtab_section, name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1244 if (sym_index) {
272
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1245 /* XXX: avoid adding a symbol if already
ad577f436eb7 [project @ 2003-05-24 15:46:29 by bellard]
bellard
parents: 268
diff changeset
1246 present because of -rdynamic ? */
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1247 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1248 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1249 sym->st_info, 0,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1250 sym->st_shndx, name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1251 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1252 if (ELF32_ST_BIND(esym->st_info) == STB_WEAK) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1253 /* weak symbols can stay undefined */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1254 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1255 warning("undefined dynamic symbol '%s'", name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1256 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1257 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1258 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1259 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1260 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1261 int nb_syms;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1262 /* shared library case : we simply export all the global symbols */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1263 nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
1264 s1->symtab_to_dynsym = xzmalloc(sizeof(int) * nb_syms);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1265 for(sym = (Elf32_Sym *)symtab_section->data + 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1266 sym < sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1267 sym++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1268 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1269 name = symtab_section->link->data + sym->st_name;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1270 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1271 sym->st_info, 0,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1272 sym->st_shndx, name);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1273 s1->symtab_to_dynsym[sym -
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1274 (Elf32_Sym *)symtab_section->data] =
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1275 index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1276 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1277 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1278 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1279
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1280 build_got_entries(s1);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1281
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1282 /* add a list of needed dlls */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1283 for(i = 0; i < s1->nb_loaded_dlls; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1284 DLLReference *dllref = s1->loaded_dlls[i];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1285 if (dllref->level == 0)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1286 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1287 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1288 /* XXX: currently, since we do not handle PIC code, we
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1289 must relocate the readonly segments */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1290 if (file_type == TCC_OUTPUT_DLL)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1291 put_dt(dynamic, DT_TEXTREL, 0);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1292
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1293 /* add necessary space for other entries */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1294 saved_dynamic_data_offset = dynamic->data_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1295 dynamic->data_offset += 8 * 9;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1296 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1297 /* still need to build got entries in case of static link */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1298 build_got_entries(s1);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1299 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1300 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1301
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1302 memset(&ehdr, 0, sizeof(ehdr));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1303
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1304 /* we add a section for symbols */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1305 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1306 put_elf_str(strsec, "");
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1307
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1308 /* compute number of sections */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1309 shnum = s1->nb_sections;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1310
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1311 /* this array is used to reorder sections in the output file */
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
1312 section_order = xmalloc(sizeof(int) * shnum);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1313 section_order[0] = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1314 sh_order_index = 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1315
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1316 /* compute number of program headers */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1317 switch(file_type) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1318 default:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1319 case TCC_OUTPUT_OBJ:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1320 phnum = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1321 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1322 case TCC_OUTPUT_EXE:
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1323 if (!tccg_static_link)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1324 phnum = 4;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1325 else
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1326 phnum = 2;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1327 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1328 case TCC_OUTPUT_DLL:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1329 phnum = 3;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1330 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1331 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1332
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1333 /* allocate strings for section names and decide if an unallocated
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1334 section should be output */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1335 /* NOTE: the strsec section comes last, so its size is also
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1336 correct ! */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1337 for(i = 1; i < s1->nb_sections; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1338 s = s1->sections[i];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1339 s->sh_name = put_elf_str(strsec, s->name);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1340 /* when generating a DLL, we include relocations but we may
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1341 patch them */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1342 if (file_type == TCC_OUTPUT_DLL &&
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1343 s->sh_type == SHT_REL &&
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1344 !(s->sh_flags & SHF_ALLOC)) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1345 prepare_dynamic_rel(s1, s);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1346 } else if (do_debug ||
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1347 file_type == TCC_OUTPUT_OBJ ||
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1348 (s->sh_flags & SHF_ALLOC) ||
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1349 i == (s1->nb_sections - 1)) {
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1350 /* we output all sections if debug or object file */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1351 s->sh_size = s->data_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1352 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1353 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1354
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1355 /* allocate program segment headers */
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
1356 phdr = xzmalloc(phnum * sizeof(Elf32_Phdr));
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1357
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1358 if (tccg_output_format == TCC_OUTPUT_FORMAT_ELF) {
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1359 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1360 } else {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1361 file_offset = 0;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1362 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1363 if (phnum > 0) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1364 /* compute section to program header mapping */
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1365 if (tccg_has_text_addr) {
319
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1366 int a_offset, p_offset;
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1367 addr = tccg_text_addr;
319
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1368 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1369 ELF_PAGE_SIZE */
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1370 a_offset = addr & (ELF_PAGE_SIZE - 1);
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1371 p_offset = file_offset & (ELF_PAGE_SIZE - 1);
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1372 if (a_offset < p_offset)
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1373 a_offset += ELF_PAGE_SIZE;
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1374 file_offset += (a_offset - p_offset);
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1375 } else {
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1376 if (file_type == TCC_OUTPUT_DLL)
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1377 addr = 0;
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1378 else
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1379 addr = ELF_START_ADDR;
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1380 /* compute address after headers */
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1381 addr += (file_offset & (ELF_PAGE_SIZE - 1));
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1382 }
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1383
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1384 /* dynamic relocation table information, for .dynamic section */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1385 rel_size = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1386 rel_addr = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1387
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1388 /* leave one program header for the program interpreter */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1389 ph = &phdr[0];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1390 if (interp)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1391 ph++;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1392
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1393 for(j = 0; j < 2; j++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1394 ph->p_type = PT_LOAD;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1395 if (j == 0)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1396 ph->p_flags = PF_R | PF_X;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1397 else
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1398 ph->p_flags = PF_R | PF_W;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1399 ph->p_align = ELF_PAGE_SIZE;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1400
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1401 /* we do the following ordering: interp, symbol tables,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1402 relocations, progbits, nobits */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1403 /* XXX: do faster and simpler sorting */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1404 for(k = 0; k < 5; k++) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1405 for(i = 1; i < s1->nb_sections; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1406 s = s1->sections[i];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1407 /* compute if section should be included */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1408 if (j == 0) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1409 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1410 SHF_ALLOC)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1411 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1412 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1413 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1414 (SHF_ALLOC | SHF_WRITE))
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1415 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1416 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1417 if (s == interp) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1418 if (k != 0)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1419 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1420 } else if (s->sh_type == SHT_DYNSYM ||
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1421 s->sh_type == SHT_STRTAB ||
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1422 s->sh_type == SHT_HASH) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1423 if (k != 1)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1424 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1425 } else if (s->sh_type == SHT_REL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1426 if (k != 2)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1427 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1428 } else if (s->sh_type == SHT_NOBITS) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1429 if (k != 4)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1430 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1431 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1432 if (k != 3)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1433 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1434 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1435 section_order[sh_order_index++] = i;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1436
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1437 /* section matches: we align it and add its size */
319
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1438 tmp = addr;
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1439 addr = (addr + s->sh_addralign - 1) &
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1440 ~(s->sh_addralign - 1);
319
547ec1d1e85a [project @ 2004-10-18 00:20:26 by bellard]
bellard
parents: 309
diff changeset
1441 file_offset += addr - tmp;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1442 s->sh_offset = file_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1443 s->sh_addr = addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1444
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1445 /* update program header infos */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1446 if (ph->p_offset == 0) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1447 ph->p_offset = file_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1448 ph->p_vaddr = addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1449 ph->p_paddr = ph->p_vaddr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1450 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1451 /* update dynamic relocation infos */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1452 if (s->sh_type == SHT_REL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1453 if (rel_size == 0)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1454 rel_addr = addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1455 rel_size += s->sh_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1456 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1457 addr += s->sh_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1458 if (s->sh_type != SHT_NOBITS)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1459 file_offset += s->sh_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1460 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1461 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1462 ph->p_filesz = file_offset - ph->p_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1463 ph->p_memsz = addr - ph->p_vaddr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1464 ph++;
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1465 if (j == 0) {
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1466 if (tccg_output_format == TCC_OUTPUT_FORMAT_ELF) {
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1467 /* if in the middle of a page, we duplicate the page in
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1468 memory so that one copy is RX and the other is RW */
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1469 if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1470 addr += ELF_PAGE_SIZE;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1471 } else {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1472 addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1473 file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1474 ~(ELF_PAGE_SIZE - 1);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1475 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1476 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1477 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1478
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1479 /* if interpreter, then add corresponing program header */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1480 if (interp) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1481 ph = &phdr[0];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1482
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1483 ph->p_type = PT_INTERP;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1484 ph->p_offset = interp->sh_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1485 ph->p_vaddr = interp->sh_addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1486 ph->p_paddr = ph->p_vaddr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1487 ph->p_filesz = interp->sh_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1488 ph->p_memsz = interp->sh_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1489 ph->p_flags = PF_R;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1490 ph->p_align = interp->sh_addralign;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1491 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1492
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1493 /* if dynamic section, then add corresponing program header */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1494 if (dynamic) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1495 Elf32_Sym *sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1496
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1497 ph = &phdr[phnum - 1];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1498
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1499 ph->p_type = PT_DYNAMIC;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1500 ph->p_offset = dynamic->sh_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1501 ph->p_vaddr = dynamic->sh_addr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1502 ph->p_paddr = ph->p_vaddr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1503 ph->p_filesz = dynamic->sh_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1504 ph->p_memsz = dynamic->sh_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1505 ph->p_flags = PF_R | PF_W;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1506 ph->p_align = dynamic->sh_addralign;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1507
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1508 /* put GOT dynamic section address */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1509 put32(s1->got->data, dynamic->sh_addr);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1510
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1511 /* relocate the PLT */
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1512 if (file_type == TCC_OUTPUT_EXE) {
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1513 uint8_t *p, *p_end;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1514
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1515 p = s1->plt->data;
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1516 p_end = p + s1->plt->data_offset;
255
e02822de9d86 [project @ 2003-04-27 11:45:01 by bellard]
bellard
parents: 248
diff changeset
1517 if (p < p_end) {
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
1518 #if defined(TINYCC_TARGET_I386)
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1519 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
255
e02822de9d86 [project @ 2003-04-27 11:45:01 by bellard]
bellard
parents: 248
diff changeset
1520 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1521 p += 16;
255
e02822de9d86 [project @ 2003-04-27 11:45:01 by bellard]
bellard
parents: 248
diff changeset
1522 while (p < p_end) {
e02822de9d86 [project @ 2003-04-27 11:45:01 by bellard]
bellard
parents: 248
diff changeset
1523 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
e02822de9d86 [project @ 2003-04-27 11:45:01 by bellard]
bellard
parents: 248
diff changeset
1524 p += 16;
e02822de9d86 [project @ 2003-04-27 11:45:01 by bellard]
bellard
parents: 248
diff changeset
1525 }
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
1526 #elif defined(TINYCC_TARGET_ARM)
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1527 int x;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1528 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1529 p +=16;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1530 while (p < p_end) {
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1531 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1532 p += 16;
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1533 }
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
1534 #elif defined(TINYCC_TARGET_C67)
305
db91cc43c90a [project @ 2004-10-04 21:57:35 by bellard]
bellard
parents: 295
diff changeset
1535 /* XXX: TODO */
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1536 #else
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1537 #error unsupported CPU
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1538 #endif
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1539 }
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1540 }
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1541
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1542 /* relocate symbols in .dynsym */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1543 sym_end = (Elf32_Sym *)(s1->dynsym->data + s1->dynsym->data_offset);
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1544 for(sym = (Elf32_Sym *)s1->dynsym->data + 1;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1545 sym < sym_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1546 sym++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1547 if (sym->st_shndx == SHN_UNDEF) {
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1548 /* relocate to the PLT if the symbol corresponds
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1549 to a PLT entry */
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1550 if (sym->st_value)
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1551 sym->st_value += s1->plt->sh_addr;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1552 } else if (sym->st_shndx < SHN_LORESERVE) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1553 /* do symbol relocation */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1554 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1555 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1556 }
228
f41bbafa11bf [project @ 2003-04-13 14:38:05 by bellard]
bellard
parents: 212
diff changeset
1557
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1558 /* put dynamic section entries */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1559 dynamic->data_offset = saved_dynamic_data_offset;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1560 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1561 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1562 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1563 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1564 put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1565 put_dt(dynamic, DT_REL, rel_addr);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1566 put_dt(dynamic, DT_RELSZ, rel_size);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1567 put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1568 put_dt(dynamic, DT_NULL, 0);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1569 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1570
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1571 ehdr.e_phentsize = sizeof(Elf32_Phdr);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1572 ehdr.e_phnum = phnum;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1573 ehdr.e_phoff = sizeof(Elf32_Ehdr);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1574 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1575
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1576 /* all other sections come after */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1577 for(i = 1; i < s1->nb_sections; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1578 s = s1->sections[i];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1579 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1580 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1581 section_order[sh_order_index++] = i;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1582
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1583 file_offset = (file_offset + s->sh_addralign - 1) &
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1584 ~(s->sh_addralign - 1);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1585 s->sh_offset = file_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1586 if (s->sh_type != SHT_NOBITS)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1587 file_offset += s->sh_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1588 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1589
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1590 /* if building executable or DLL, then relocate each section
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1591 except the GOT which is already relocated */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1592 if (file_type != TCC_OUTPUT_OBJ) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1593 relocate_syms(s1, 0);
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1594
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1595 if (s1->nb_errors != 0) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1596 fail:
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1597 ret = -1;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1598 goto the_end;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1599 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1600
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1601 /* relocate sections */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1602 /* XXX: ignore sections with allocated relocations ? */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1603 for(i = 1; i < s1->nb_sections; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1604 s = s1->sections[i];
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1605 if (s->reloc && s != s1->got)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1606 relocate_section(s1, s);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1607 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1608
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1609 /* relocate relocation entries if the relocation tables are
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1610 allocated in the executable */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1611 for(i = 1; i < s1->nb_sections; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1612 s = s1->sections[i];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1613 if ((s->sh_flags & SHF_ALLOC) &&
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1614 s->sh_type == SHT_REL) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1615 relocate_rel(s1, s);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1616 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1617 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1618
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1619 /* get entry point address */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1620 if (file_type == TCC_OUTPUT_EXE)
283
5bd410aefdc4 [project @ 2003-07-20 19:19:58 by bellard]
bellard
parents: 278
diff changeset
1621 ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1622 else
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1623 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1624 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1625
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1626 /* write elf file */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1627 if (file_type == TCC_OUTPUT_OBJ)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1628 mode = 0666;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1629 else
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1630 mode = 0777;
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1631 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1632 if (fd < 0) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1633 error_noabort("could not write '%s'", filename);
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1634 goto fail;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1635 }
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1636 f = fdopen(fd, "wb");
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1637
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
1638 #ifdef TINYCC_TARGET_COFF
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1639 if (tccg_output_format == TCC_OUTPUT_FORMAT_COFF) {
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1640 tcc_output_coff(s1, f);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1641 } else
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1642 #endif
554
8c020de0af57 Fix earlier options.c break-up by migrating some stuff from tcc.h to tinycc.h.
Rob Landley <rob@landley.net>
parents: 553
diff changeset
1643 if (tccg_output_format == TCC_OUTPUT_FORMAT_ELF) {
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1644 sort_syms(s1, symtab_section);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1645
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1646 /* align to 4 */
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1647 file_offset = (file_offset + 3) & -4;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1648
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1649 /* fill header */
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1650 ehdr.e_ident[0] = ELFMAG0;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1651 ehdr.e_ident[1] = ELFMAG1;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1652 ehdr.e_ident[2] = ELFMAG2;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1653 ehdr.e_ident[3] = ELFMAG3;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1654 ehdr.e_ident[4] = ELFCLASS32;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1655 ehdr.e_ident[5] = ELFDATA2LSB;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1656 ehdr.e_ident[6] = EV_CURRENT;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1657 #ifdef __FreeBSD__
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1658 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1659 #endif
555
646f1f0972b6 Update TCC_TARGET_* to TINYCC_TARGET_* (which is what new build sets).
Rob Landley <rob@landley.net>
parents: 554
diff changeset
1660 #ifdef TINYCC_TARGET_ARM
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
1661 #ifdef TCC_ARM_EABI
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
1662 ehdr.e_ident[EI_OSABI] = 0;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
1663 ehdr.e_flags = 4 << 24;
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
1664 #else
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1665 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1666 #endif
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
1667 #endif
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1668 switch(file_type) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1669 default:
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1670 case TCC_OUTPUT_EXE:
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1671 ehdr.e_type = ET_EXEC;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1672 break;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1673 case TCC_OUTPUT_DLL:
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1674 ehdr.e_type = ET_DYN;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1675 break;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1676 case TCC_OUTPUT_OBJ:
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1677 ehdr.e_type = ET_REL;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1678 break;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1679 }
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1680 ehdr.e_machine = EM_TCC_TARGET;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1681 ehdr.e_version = EV_CURRENT;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1682 ehdr.e_shoff = file_offset;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1683 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1684 ehdr.e_shentsize = sizeof(Elf32_Shdr);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1685 ehdr.e_shnum = shnum;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1686 ehdr.e_shstrndx = shnum - 1;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1687
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1688 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1689 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1690 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1691
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1692 for(i=1;i<s1->nb_sections;i++) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1693 s = s1->sections[section_order[i]];
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1694 if (s->sh_type != SHT_NOBITS) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1695 while (offset < s->sh_offset) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1696 fputc(0, f);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1697 offset++;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1698 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1699 size = s->sh_size;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1700 fwrite(s->data, 1, size, f);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1701 offset += size;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1702 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1703 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1704
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1705 /* output section headers */
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1706 while (offset < ehdr.e_shoff) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1707 fputc(0, f);
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1708 offset++;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1709 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1710
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1711 for(i=0;i<s1->nb_sections;i++) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1712 sh = &shdr;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1713 memset(sh, 0, sizeof(Elf32_Shdr));
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1714 s = s1->sections[i];
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1715 if (s) {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1716 sh->sh_name = s->sh_name;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1717 sh->sh_type = s->sh_type;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1718 sh->sh_flags = s->sh_flags;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1719 sh->sh_entsize = s->sh_entsize;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1720 sh->sh_info = s->sh_info;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1721 if (s->link)
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1722 sh->sh_link = s->link->sh_num;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1723 sh->sh_addralign = s->sh_addralign;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1724 sh->sh_addr = s->sh_addr;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1725 sh->sh_offset = s->sh_offset;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1726 sh->sh_size = s->sh_size;
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1727 }
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1728 fwrite(sh, 1, sizeof(Elf32_Shdr), f);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1729 }
325
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1730 } else {
0a6b6ad4b159 [project @ 2004-10-23 22:53:42 by bellard]
bellard
parents: 319
diff changeset
1731 tcc_output_binary(s1, f, section_order);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1732 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1733 fclose(f);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1734
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1735 ret = 0;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1736 the_end:
481
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1737 free(s1->symtab_to_dynsym);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1738 free(section_order);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1739 free(phdr);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1740 free(s1->got_offsets);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1741 return ret;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1742 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1743
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1744 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1745 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1746 void *data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1747
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
1748 data = xmalloc(size);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1749 lseek(fd, file_offset, SEEK_SET);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1750 read(fd, data, size);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1751 return data;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1752 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1753
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1754 typedef struct SectionMergeInfo {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1755 Section *s; /* corresponding existing section */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1756 unsigned long offset; /* offset of the new section in the existing section */
287
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1757 uint8_t new_section; /* true if section 's' was added */
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1758 uint8_t link_once; /* true if link once section */
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1759 } SectionMergeInfo;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1760
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1761 /* load an object file and merge it with current files */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1762 /* XXX: handle correctly stab (debug) info */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1763 static int tcc_load_object_file(TCCState *s1,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1764 int fd, unsigned long file_offset)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1765 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1766 Elf32_Ehdr ehdr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1767 Elf32_Shdr *shdr, *sh;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1768 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1769 unsigned char *strsec, *strtab;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1770 int *old_to_new_syms;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1771 char *sh_name, *name;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1772 SectionMergeInfo *sm_table, *sm;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1773 Elf32_Sym *sym, *symtab;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1774 Elf32_Rel *rel, *rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1775 Section *s;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1776
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1777 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1778 goto fail1;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1779 if (ehdr.e_ident[0] != ELFMAG0 ||
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1780 ehdr.e_ident[1] != ELFMAG1 ||
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1781 ehdr.e_ident[2] != ELFMAG2 ||
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1782 ehdr.e_ident[3] != ELFMAG3)
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1783 goto fail1;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1784 /* test if object file */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1785 if (ehdr.e_type != ET_REL)
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1786 goto fail1;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1787 /* test CPU specific stuff */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1788 if (ehdr.e_ident[5] != ELFDATA2LSB ||
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
1789 ehdr.e_machine != EM_TCC_TARGET) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1790 fail1:
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1791 error_noabort("invalid object file");
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1792 return -1;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1793 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1794 /* read sections */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1795 shdr = load_data(fd, file_offset + ehdr.e_shoff,
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1796 sizeof(Elf32_Shdr) * ehdr.e_shnum);
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
1797 sm_table = xzmalloc(sizeof(SectionMergeInfo) * ehdr.e_shnum);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1798
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1799 /* load section names */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1800 sh = &shdr[ehdr.e_shstrndx];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1801 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1802
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1803 /* load symtab and strtab */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1804 old_to_new_syms = NULL;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1805 symtab = NULL;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1806 strtab = NULL;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1807 nb_syms = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1808 for(i = 1; i < ehdr.e_shnum; i++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1809 sh = &shdr[i];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1810 if (sh->sh_type == SHT_SYMTAB) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1811 if (symtab) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1812 error_noabort("object must contain only one symtab");
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1813 fail:
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1814 ret = -1;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1815 goto the_end;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1816 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1817 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1818 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1819 sm_table[i].s = symtab_section;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1820
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1821 /* now load strtab */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1822 sh = &shdr[sh->sh_link];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1823 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1824 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1825 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1826
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1827 /* now examine each section and try to merge its content with the
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1828 ones in memory */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1829 for(i = 1; i < ehdr.e_shnum; i++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1830 /* no need to examine section name strtab */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1831 if (i == ehdr.e_shstrndx)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1832 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1833 sh = &shdr[i];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1834 sh_name = strsec + sh->sh_name;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1835 /* ignore sections types we do not handle */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1836 if (sh->sh_type != SHT_PROGBITS &&
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1837 sh->sh_type != SHT_REL &&
409
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
1838 #ifdef TCC_ARM_EABI
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
1839 sh->sh_type != SHT_ARM_EXIDX &&
41f19a7b4093 Support for ARM EABI, by Daniel Glockner.
landley@driftwood
parents: 396
diff changeset
1840 #endif
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1841 sh->sh_type != SHT_NOBITS)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1842 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1843 if (sh->sh_addralign < 1)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1844 sh->sh_addralign = 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1845 /* find corresponding section, if any */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1846 for(j = 1; j < s1->nb_sections;j++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1847 s = s1->sections[j];
287
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1848 if (!strcmp(s->name, sh_name)) {
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1849 if (!strncmp(sh_name, ".gnu.linkonce",
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1850 sizeof(".gnu.linkonce") - 1)) {
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1851 /* if a 'linkonce' section is already present, we
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1852 do not add it again. It is a little tricky as
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1853 symbols can still be defined in
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1854 it. */
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1855 sm_table[i].link_once = 1;
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1856 goto next;
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1857 } else {
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1858 goto found;
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1859 }
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1860 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1861 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1862 /* not found: create new section */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1863 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1864 /* take as much info as possible from the section. sh_link and
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1865 sh_info will be updated later */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1866 s->sh_addralign = sh->sh_addralign;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1867 s->sh_entsize = sh->sh_entsize;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1868 sm_table[i].new_section = 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1869 found:
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1870 if (sh->sh_type != s->sh_type) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1871 error_noabort("invalid section type");
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1872 goto fail;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1873 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1874
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1875 /* align start of section */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1876 offset = s->data_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1877 size = sh->sh_addralign - 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1878 offset = (offset + size) & ~size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1879 if (sh->sh_addralign > s->sh_addralign)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1880 s->sh_addralign = sh->sh_addralign;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1881 s->data_offset = offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1882 sm_table[i].offset = offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1883 sm_table[i].s = s;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1884 /* concatenate sections */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1885 size = sh->sh_size;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1886 if (sh->sh_type != SHT_NOBITS) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1887 unsigned char *ptr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1888 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
151
0b7f99853067 [project @ 2002-08-18 14:34:57 by bellard]
bellard
parents: 140
diff changeset
1889 ptr = section_ptr_add(s, size);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1890 read(fd, ptr, size);
151
0b7f99853067 [project @ 2002-08-18 14:34:57 by bellard]
bellard
parents: 140
diff changeset
1891 } else {
0b7f99853067 [project @ 2002-08-18 14:34:57 by bellard]
bellard
parents: 140
diff changeset
1892 s->data_offset += size;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1893 }
287
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1894 next: ;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1895 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1896
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1897 /* second short pass to update sh_link and sh_info fields of new
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1898 sections */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1899 for(i = 1; i < ehdr.e_shnum; i++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1900 s = sm_table[i].s;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1901 if (!s || !sm_table[i].new_section)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1902 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1903 sh = &shdr[i];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1904 if (sh->sh_link > 0)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1905 s->link = sm_table[sh->sh_link].s;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1906 if (sh->sh_type == SHT_REL) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1907 s->sh_info = sm_table[sh->sh_info].s->sh_num;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1908 /* update backward link */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1909 s1->sections[s->sh_info]->reloc = s;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1910 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1911 }
396
928147ea8ab6 Fix "invalid relocation entry" problem on ubuntu. Fix from Bernhard
landley@driftwood
parents: 394
diff changeset
1912 sm = sm_table;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1913
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1914 /* resolve symbols */
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
1915 old_to_new_syms = xzmalloc(nb_syms * sizeof(int));
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1916
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1917 sym = symtab + 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1918 for(i = 1; i < nb_syms; i++, sym++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1919 if (sym->st_shndx != SHN_UNDEF &&
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1920 sym->st_shndx < SHN_LORESERVE) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1921 sm = &sm_table[sym->st_shndx];
287
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1922 if (sm->link_once) {
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1923 /* if a symbol is in a link once section, we use the
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1924 already defined symbol. It is very important to get
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1925 correct relocations */
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1926 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1927 name = strtab + sym->st_name;
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1928 sym_index = find_elf_sym(symtab_section, name);
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1929 if (sym_index)
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1930 old_to_new_syms[i] = sym_index;
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1931 }
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1932 continue;
462860741295 [project @ 2003-10-04 14:45:23 by bellard]
bellard
parents: 283
diff changeset
1933 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1934 /* if no corresponding section added, no need to add symbol */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1935 if (!sm->s)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1936 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1937 /* convert section number */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1938 sym->st_shndx = sm->s->sh_num;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1939 /* offset value */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1940 sym->st_value += sm->offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1941 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1942 /* add symbol */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1943 name = strtab + sym->st_name;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1944 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
356
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
1945 sym->st_info, sym->st_other,
4765ed8785f5 [project @ 2005-04-13 21:37:06 by bellard]
bellard
parents: 350
diff changeset
1946 sym->st_shndx, name);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1947 old_to_new_syms[i] = sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1948 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1949
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1950 /* third pass to patch relocation entries */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1951 for(i = 1; i < ehdr.e_shnum; i++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1952 s = sm_table[i].s;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1953 if (!s)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1954 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1955 sh = &shdr[i];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1956 offset = sm_table[i].offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1957 switch(s->sh_type) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1958 case SHT_REL:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1959 /* take relocation offset information */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1960 offseti = sm_table[sh->sh_info].offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1961 rel_end = (Elf32_Rel *)(s->data + s->data_offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1962 for(rel = (Elf32_Rel *)(s->data + offset);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1963 rel < rel_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1964 rel++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1965 int type;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1966 unsigned sym_index;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1967 /* convert symbol index */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1968 type = ELF32_R_TYPE(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1969 sym_index = ELF32_R_SYM(rel->r_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1970 /* NOTE: only one symtab assumed */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1971 if (sym_index >= nb_syms)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1972 goto invalid_reloc;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1973 sym_index = old_to_new_syms[sym_index];
396
928147ea8ab6 Fix "invalid relocation entry" problem on ubuntu. Fix from Bernhard
landley@driftwood
parents: 394
diff changeset
1974 /* ignore link_once in rel section. */
928147ea8ab6 Fix "invalid relocation entry" problem on ubuntu. Fix from Bernhard
landley@driftwood
parents: 394
diff changeset
1975 if (!sym_index && !sm->link_once) {
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1976 invalid_reloc:
396
928147ea8ab6 Fix "invalid relocation entry" problem on ubuntu. Fix from Bernhard
landley@driftwood
parents: 394
diff changeset
1977 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
928147ea8ab6 Fix "invalid relocation entry" problem on ubuntu. Fix from Bernhard
landley@driftwood
parents: 394
diff changeset
1978 i, strsec + sh->sh_name, rel->r_offset);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1979 goto fail;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1980 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1981 rel->r_info = ELF32_R_INFO(sym_index, type);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1982 /* offset the relocation offset */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1983 rel->r_offset += offseti;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1984 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1985 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1986 default:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1987 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1988 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
1989 }
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1990
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1991 ret = 0;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1992 the_end:
481
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1993 free(symtab);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1994 free(strtab);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1995 free(old_to_new_syms);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1996 free(sm_table);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1997 free(strsec);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
1998 free(shdr);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
1999 return ret;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2000 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2001
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2002 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2003
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2004 typedef struct ArchiveHeader {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2005 char ar_name[16]; /* name of this member */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2006 char ar_date[12]; /* file mtime */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2007 char ar_uid[6]; /* owner uid; printed as decimal */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2008 char ar_gid[6]; /* owner gid; printed as decimal */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2009 char ar_mode[8]; /* file mode, printed as octal */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2010 char ar_size[10]; /* file size, printed as decimal */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2011 char ar_fmag[2]; /* should contain ARFMAG */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2012 } ArchiveHeader;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2013
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
2014 static int get_be32(uint8_t *b)
259
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2015 {
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2016 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2017 }
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2018
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2019 /* load only the objects which resolve undefined symbols */
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2020 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2021 {
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2022 int i, bound, nsyms, sym_index, off, ret;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2023 uint8_t *data;
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
2024 char *ar_names, *p;
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
2025 uint8_t *ar_index;
259
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2026 Elf32_Sym *sym;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2027
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
2028 data = xmalloc(size);
259
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2029 if (read(fd, data, size) != size)
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2030 goto fail;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2031 nsyms = get_be32(data);
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2032 ar_index = data + 4;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2033 ar_names = ar_index + nsyms * 4;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2034
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2035 do {
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2036 bound = 0;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2037 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2038 sym_index = find_elf_sym(symtab_section, p);
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2039 if(sym_index) {
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2040 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2041 if(sym->st_shndx == SHN_UNDEF) {
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2042 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2043 #if 0
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2044 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2045 #endif
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2046 ++bound;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2047 lseek(fd, off, SEEK_SET);
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2048 if(tcc_load_object_file(s1, fd, off) < 0) {
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2049 fail:
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2050 ret = -1;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2051 goto the_end;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2052 }
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2053 }
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2054 }
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2055 }
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2056 } while(bound);
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2057 ret = 0;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2058 the_end:
481
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
2059 free(data);
259
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2060 return ret;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2061 }
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2062
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2063 /* load a '.a' file */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2064 static int tcc_load_archive(TCCState *s1, int fd)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2065 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2066 ArchiveHeader hdr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2067 char ar_size[11];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2068 char ar_name[17];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2069 char magic[8];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2070 int size, len, i;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2071 unsigned long file_offset;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2072
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2073 /* skip magic which was already checked */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2074 read(fd, magic, sizeof(magic));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2075
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2076 for(;;) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2077 len = read(fd, &hdr, sizeof(hdr));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2078 if (len == 0)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2079 break;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2080 if (len != sizeof(hdr)) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2081 error_noabort("invalid archive");
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2082 return -1;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2083 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2084 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2085 ar_size[sizeof(hdr.ar_size)] = '\0';
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2086 size = strtol(ar_size, NULL, 0);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2087 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2088 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2089 if (ar_name[i] != ' ')
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2090 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2091 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2092 ar_name[i + 1] = '\0';
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2093 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2094 file_offset = lseek(fd, 0, SEEK_CUR);
259
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2095 /* align to even */
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2096 size = (size + 1) & ~1;
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2097 if (!strcmp(ar_name, "/")) {
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2098 /* coff symbol table : we handle it */
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2099 if(s1->alacarte_link)
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2100 return tcc_load_alacarte(s1, fd, size);
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2101 } else if (!strcmp(ar_name, "//") ||
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2102 !strcmp(ar_name, "__.SYMDEF") ||
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2103 !strcmp(ar_name, "__.SYMDEF/") ||
1835379353e4 [project @ 2003-04-28 22:06:38 by bellard]
bellard
parents: 255
diff changeset
2104 !strcmp(ar_name, "ARFILENAMES/")) {
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2105 /* skip symbol table or archive names */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2106 } else {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2107 if (tcc_load_object_file(s1, fd, file_offset) < 0)
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2108 return -1;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2109 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2110 lseek(fd, file_offset + size, SEEK_SET);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2111 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2112 return 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2113 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2114
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2115 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2116 is referenced by the user (so it should be added as DT_NEEDED in
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2117 the generated ELF file) */
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
2118 static int tcc_load_dll(TCCState *s1, int fd, char *filename, int level)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2119 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2120 Elf32_Ehdr ehdr;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2121 Elf32_Shdr *shdr, *sh, *sh1;
394
d8081c1ea611 [project @ 2005-10-30 21:53:14 by bellard]
bellard
parents: 383
diff changeset
2122 int i, j, nb_syms, nb_dts, sym_bind, ret;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2123 Elf32_Sym *sym, *dynsym;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2124 Elf32_Dyn *dt, *dynamic;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2125 unsigned char *dynstr;
553
4533aa54ffcf More simplification and attacking warnings.
Rob Landley <rob@landley.net>
parents: 547
diff changeset
2126 char *name, *soname, *p;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2127 DLLReference *dllref;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2128
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2129 read(fd, &ehdr, sizeof(ehdr));
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2130
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2131 /* test CPU specific stuff */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2132 if (ehdr.e_ident[5] != ELFDATA2LSB ||
295
3a3d42516bbd [project @ 2003-10-14 22:15:56 by bellard]
bellard
parents: 289
diff changeset
2133 ehdr.e_machine != EM_TCC_TARGET) {
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2134 error_noabort("bad architecture");
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2135 return -1;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2136 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2137
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2138 /* read sections */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2139 shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2141 /* load dynamic section and dynamic symbols */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2142 nb_syms = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2143 nb_dts = 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2144 dynamic = NULL;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2145 dynsym = NULL; /* avoid warning */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2146 dynstr = NULL; /* avoid warning */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2147 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2148 switch(sh->sh_type) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2149 case SHT_DYNAMIC:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2150 nb_dts = sh->sh_size / sizeof(Elf32_Dyn);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2151 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2152 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2153 case SHT_DYNSYM:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2154 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2155 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2156 sh1 = &shdr[sh->sh_link];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2157 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2158 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2159 default:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2160 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2161 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2162 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2163
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2164 /* compute the real library name */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2165 soname = filename;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2166 p = strrchr(soname, '/');
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2167 if (p)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2168 soname = p + 1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2169
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2170 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2171 if (dt->d_tag == DT_SONAME) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2172 soname = dynstr + dt->d_un.d_val;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2173 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2174 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2175
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2176 /* if the dll is already loaded, do not load it */
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2177 for(i = 0; i < s1->nb_loaded_dlls; i++) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2178 dllref = s1->loaded_dlls[i];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2179 if (!strcmp(soname, dllref->name)) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2180 /* but update level if needed */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2181 if (level < dllref->level)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2182 dllref->level = level;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2183 ret = 0;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2184 goto the_end;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2185 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2186 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2187
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2188 // printf("loading dll '%s'\n", soname);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2189
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2190 /* add the dll and its level */
507
67453c7d623e Clean up malloc() and friends to xmalloc/xzmalloc/xstrdup, and remove redundant
Rob Landley <rob@landley.net>
parents: 505
diff changeset
2191 dllref = xmalloc(sizeof(DLLReference) + strlen(soname));
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2192 dllref->level = level;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2193 strcpy(dllref->name, soname);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2194 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2195
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2196 /* add dynamic symbols in dynsym_section */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2197 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2198 sym_bind = ELF32_ST_BIND(sym->st_info);
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2199 if (sym_bind == STB_LOCAL)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2200 continue;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2201 name = dynstr + sym->st_name;
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2202 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
372
a8da3b580b5e [project @ 2005-04-17 13:15:54 by bellard]
bellard
parents: 356
diff changeset
2203 sym->st_info, sym->st_other, sym->st_shndx, name);
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2204 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2205
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2206 /* load all referenced DLLs */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2207 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2208 switch(dt->d_tag) {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2209 case DT_NEEDED:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2210 name = dynstr + dt->d_un.d_val;
394
d8081c1ea611 [project @ 2005-10-30 21:53:14 by bellard]
bellard
parents: 383
diff changeset
2211 for(j = 0; j < s1->nb_loaded_dlls; j++) {
d8081c1ea611 [project @ 2005-10-30 21:53:14 by bellard]
bellard
parents: 383
diff changeset
2212 dllref = s1->loaded_dlls[j];
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2213 if (!strcmp(name, dllref->name))
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2214 goto already_loaded;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2215 }
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2216 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2217 error_noabort("referenced dll '%s' not found", name);
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2218 ret = -1;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2219 goto the_end;
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2220 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2221 already_loaded:
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2222 break;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2223 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2224 }
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2225 ret = 0;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2226 the_end:
481
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
2227 free(dynstr);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
2228 free(dynsym);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
2229 free(dynamic);
0f5c38ddf450 Remove MEM_DEBUG and now-useless tcc_free() wrapper. Now, would anyone like to
Rob Landley <rob@landley.net>
parents: 479
diff changeset
2230 free(shdr);
174
25a3b0879649 [project @ 2002-11-02 14:13:21 by bellard]
bellard
parents: 172
diff changeset
2231 return ret;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2232 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2233
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2234 #define LD_TOK_NAME 256
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2235 #define LD_TOK_EOF (-1)
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2236
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2237 /* return next ld script token */
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2238 static int ld_next(TCCState *s1, char *name, int name_size)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2239 {
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2240 int c;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2241 char *q;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2242
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2243 redo:
479
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2244 switch(fch) {
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2245 case ' ':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2246 case '\t':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2247 case '\f':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2248 case '\v':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2249 case '\r':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2250 case '\n':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2251 inp();
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2252 goto redo;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2253 case '/':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2254 minp();
479
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2255 if (fch == '*') {
230
78cabc8c3ca7 [project @ 2003-04-13 18:05:51 by bellard]
bellard
parents: 228
diff changeset
2256 file->buf_ptr = parse_comment(file->buf_ptr);
479
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2257 fch = file->buf_ptr[0];
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2258 goto redo;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2259 } else {
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2260 q = name;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2261 *q++ = '/';
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2262 goto parse_name;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2263 }
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2264 break;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2265 case 'a' ... 'z':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2266 case 'A' ... 'Z':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2267 case '_':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2268 case '\\':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2269 case '.':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2270 case '$':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2271 case '~':
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2272 q = name;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2273 parse_name:
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2274 for(;;) {
479
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2275 if (!((fch >= 'a' && fch <= 'z') ||
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2276 (fch >= 'A' && fch <= 'Z') ||
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2277 (fch >= '0' && fch <= '9') ||
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2278 strchr("/.-_+=$:\\,~", fch)))
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2279 break;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2280 if ((q - name) < name_size - 1) {
479
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2281 *q++ = fch;
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2282 }
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2283 minp();
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2284 }
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2285 *q = '\0';
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2286 c = LD_TOK_NAME;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2287 break;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2288 case CH_EOF:
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2289 c = LD_TOK_EOF;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2290 break;
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2291 default:
479
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2292 c = fch;
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2293 inp();
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2294 break;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2295 }
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2296 #if 0
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2297 printf("tok=%c %d\n", c, c);
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2298 if (c == LD_TOK_NAME)
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2299 printf(" name=%s\n", name);
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2300 #endif
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2301 return c;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2302 }
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2303
383
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2304 static int ld_add_file_list(TCCState *s1, int as_needed)
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2305 {
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2306 char filename[1024];
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2307 int t, ret;
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2308
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2309 t = ld_next(s1, filename, sizeof(filename));
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2310 if (t != '(')
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2311 expect("(");
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2312 t = ld_next(s1, filename, sizeof(filename));
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2313 for(;;) {
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2314 if (t == LD_TOK_EOF) {
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2315 error_noabort("unexpected end of file");
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2316 return -1;
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2317 } else if (t == ')') {
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2318 break;
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2319 } else if (t != LD_TOK_NAME) {
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2320 error_noabort("filename expected");
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2321 return -1;
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2322 }
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2323 if (!strcmp(filename, "AS_NEEDED")) {
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2324 ret = ld_add_file_list(s1, 1);
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2325 if (ret)
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2326 return ret;
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2327 } else {
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2328 /* TODO: Implement AS_NEEDED support. Ignore it for now */
564
d89a6822b7e0 Use library search path for crt?.o, and for ld script libraries with no path.
Rob Landley <rob@landley.net>
parents: 555
diff changeset
2329 if (!as_needed) {
d89a6822b7e0 Use library search path for crt?.o, and for ld script libraries with no path.
Rob Landley <rob@landley.net>
parents: 555
diff changeset
2330 if (*filename=='/') tcc_add_file(s1, filename);
d89a6822b7e0 Use library search path for crt?.o, and for ld script libraries with no path.
Rob Landley <rob@landley.net>
parents: 555
diff changeset
2331 else tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
d89a6822b7e0 Use library search path for crt?.o, and for ld script libraries with no path.
Rob Landley <rob@landley.net>
parents: 555
diff changeset
2332 }
383
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2333 }
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2334 t = ld_next(s1, filename, sizeof(filename));
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2335 if (t == ',') {
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2336 t = ld_next(s1, filename, sizeof(filename));
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2337 }
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2338 }
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2339 return 0;
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2340 }
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2341
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2342 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2343 files */
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2344 static int tcc_load_ldscript(TCCState *s1)
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2345 {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2346 char cmd[64];
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2347 char filename[1024];
383
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2348 int t, ret;
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2349
479
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2350 //fch = file->buf_ptr[0];
7909d3c7e712 Replace global "ch" with "fch" so it's slightly easier to grep for. (It's the
Rob Landley <rob@landley.net>
parents: 469
diff changeset
2351 fch = handle_eob();
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2352 for(;;) {
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2353 t = ld_next(s1, cmd, sizeof(cmd));
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2354 if (t == LD_TOK_EOF)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2355 return 0;
191
b949a4e4df91 [project @ 2002-11-22 18:12:41 by bellard]
bellard
parents: 174
diff changeset
2356 else if (t != LD_TOK_NAME)
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2357 return -1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2358 if (!strcmp(cmd, "INPUT") ||
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2359 !strcmp(cmd, "GROUP")) {
383
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2360 ret = ld_add_file_list(s1, 0);
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2361 if (ret)
7b0992df204d [project @ 2005-09-03 21:32:06 by bellard]
bellard
parents: 372
diff changeset
2362 return ret;
248
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2363 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2364 !strcmp(cmd, "TARGET")) {
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2365 /* ignore some commands */
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2366 t = ld_next(s1, cmd, sizeof(cmd));
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2367 if (t != '(')
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2368 expect("(");
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2369 for(;;) {
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2370 t = ld_next(s1, filename, sizeof(filename));
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2371 if (t == LD_TOK_EOF) {
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2372 error_noabort("unexpected end of file");
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2373 return -1;
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2374 } else if (t == ')') {
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2375 break;
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2376 }
b9c48dd2e0da [project @ 2003-04-16 21:25:59 by bellard]
bellard
parents: 230
diff changeset
2377 }
140
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2378 } else {
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2379 return -1;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2380 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2381 }
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2382 return 0;
f6fb1f65ba4d [project @ 2002-08-18 13:17:59 by bellard]
bellard
parents:
diff changeset
2383 }