Subversion Repositories Kolibri OS

Rev

Rev 145 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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