Subversion Repositories Kolibri OS

Rev

Rev 647 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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