~ubuntu-branches/ubuntu/wily/tcc/wily-proposed

« back to all changes in this revision

Viewing changes to .pc/0001-Fix-R_ARM_REL32-relocation.patch/tccelf.c

  • Committer: Package Import Robot
  • Author(s): Thomas Preud'homme
  • Date: 2012-06-13 22:31:30 UTC
  • mfrom: (1.1.7)
  • Revision ID: package-import@ubuntu.com-20120613223130-14dujlcw1bj70jrh
Tags: 0.9.26~git20120612.ad5f375-3
* debian/patches:
  + Disable the new callsave_test test on arm since it uses alloca which is
    not supported on arm (yet).

Show diffs side-by-side

added added

removed removed

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