Subversion Repositories Kolibri OS

Rev

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