*-link.c: remove stupid loops tccelf.c: ...also tccgen.c: create .tdata/.tbss sections only when needed
Unified · Split
| @@ -434,29 +434,12 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 433 unmodified lines | ||
| 434 | 434 | return; |
| 435 | 435 | case R_ARM_TLS_LE32: |
| 436 | 436 | { |
| 437 | − ElfW(Sym) *sym; | |
| 438 | − Section *sec; | |
| 439 | 437 | int32_t x; |
| 440 | − addr_t tls_start = 0, tls_end = 0, tls_align = 1; | |
| 441 | − int i; | |
| 442 | − | |
| 443 | − sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 444 | − sec = s1->sections[sym->st_shndx]; | |
| 445 | − | |
| 446 | − for (i = 1; i < s1->nb_sections; i++) { | |
| 447 | − Section *s = s1->sections[i]; | |
| 448 | − if (s->sh_flags & SHF_TLS && s->sh_size) { | |
| 449 | − if (!tls_start || s->sh_addr < tls_start) | |
| 450 | − tls_start = s->sh_addr; | |
| 451 | − if (s->sh_addr + s->sh_size > tls_end) | |
| 452 | − tls_end = s->sh_addr + s->sh_size; | |
| 453 | − if (s->sh_addralign > tls_align) | |
| 454 | − tls_align = s->sh_addralign; | |
| 455 | − } | |
| 456 | − } | |
| 457 | − if (tls_end > tls_start) { | |
| 458 | − x = val - tls_start + 8; | |
| 438 | + if (s1->tls_end) { | |
| 439 | + x = val - s1->tls_start + 8; | |
| 459 | 440 | } else { |
| 441 | + ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 442 | + Section *sec = s1->sections[sym->st_shndx]; | |
| 460 | 443 | x = val - sec->sh_addr - sec->data_offset + 8; |
| 461 | 444 | } |
| 462 | 445 | add32le(ptr, x); |
| @@ -371,17 +371,8 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 370 unmodified lines | ||
| 371 | 371 | return; |
| 372 | 372 | case R_AARCH64_TLSLE_ADD_TPREL_HI12: |
| 373 | 373 | case R_AARCH64_TLSLE_ADD_TPREL_LO12: { |
| 374 | − addr_t tls_start = 0; | |
| 375 | − int i; | |
| 376 | − for (i = 1; i < s1->nb_sections; i++) { | |
| 377 | − Section *s = s1->sections[i]; | |
| 378 | − if (s->sh_flags & SHF_TLS && s->sh_size) { | |
| 379 | − if (!tls_start || s->sh_addr < tls_start) | |
| 380 | − tls_start = s->sh_addr; | |
| 381 | − } | |
| 382 | − } | |
| 383 | 374 | /* glibc arm64: tp points to tcbhead_t (DTV), TLS data starts after it */ |
| 384 | − int64_t tp_offset = val - tls_start + 16; | |
| 375 | + int64_t tp_offset = val - s1->tls_start + 16; | |
| 385 | 376 | int64_t imm; |
| 386 | 377 | if (type == R_AARCH64_TLSLE_ADD_TPREL_HI12) |
| 387 | 378 | imm = (tp_offset >> 12) & 0xfff; |
| @@ -318,31 +318,12 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 317 unmodified lines | ||
| 318 | 318 | return; |
| 319 | 319 | case R_386_TLS_LE: |
| 320 | 320 | { |
| 321 | − ElfW(Sym) *sym; | |
| 322 | − Section *sec; | |
| 323 | 321 | int32_t x; |
| 324 | − addr_t tls_start = 0, tls_end = 0, tls_align = 1; | |
| 325 | − int i; | |
| 326 | − | |
| 327 | − sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 328 | − sec = s1->sections[sym->st_shndx]; | |
| 329 | − | |
| 330 | − for (i = 1; i < s1->nb_sections; i++) { | |
| 331 | − Section *s = s1->sections[i]; | |
| 332 | − if (s->sh_flags & SHF_TLS && s->sh_size) { | |
| 333 | − if (!tls_start || s->sh_addr < tls_start) | |
| 334 | − tls_start = s->sh_addr; | |
| 335 | − if (s->sh_addr + s->sh_size > tls_end) | |
| 336 | − tls_end = s->sh_addr + s->sh_size; | |
| 337 | − if (s->sh_addralign > tls_align) | |
| 338 | − tls_align = s->sh_addralign; | |
| 339 | − } | |
| 340 | − } | |
| 341 | − if (tls_end > tls_start) { | |
| 342 | − addr_t tls_size = tls_end - tls_start; | |
| 343 | − addr_t aligned_size = (tls_size + tls_align - 1) & ~(tls_align - 1); | |
| 344 | − x = val - (tls_start + aligned_size); | |
| 322 | + if (s1->tls_end) { | |
| 323 | + x = val - s1->tls_end; | |
| 345 | 324 | } else { |
| 325 | + ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 326 | + Section *sec = s1->sections[sym->st_shndx]; | |
| 346 | 327 | x = val - sec->sh_addr - sec->data_offset; |
| 347 | 328 | } |
| 348 | 329 | add32le(ptr, x); |
| @@ -407,17 +407,7 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 406 unmodified lines | ||
| 407 | 407 | |
| 408 | 408 | case R_RISCV_TPREL_HI20: |
| 409 | 409 | case R_RISCV_TPREL_LO12_I: { |
| 410 | − addr_t tls_start = 0; | |
| 411 | − int64_t tp_offset; | |
| 412 | − int i; | |
| 413 | − for (i = 1; i < s1->nb_sections; i++) { | |
| 414 | − Section *s = s1->sections[i]; | |
| 415 | − if (s->sh_flags & SHF_TLS && s->sh_size) { | |
| 416 | − if (!tls_start || s->sh_addr < tls_start) | |
| 417 | − tls_start = s->sh_addr; | |
| 418 | − } | |
| 419 | − } | |
| 420 | − tp_offset = val - tls_start; | |
| 410 | + int64_t tp_offset = val - s1->tls_start; | |
| 421 | 411 | if (type == R_RISCV_TPREL_HI20) { |
| 422 | 412 | off64 = (int64_t)(tp_offset + 0x800) >> 12; |
| 423 | 413 | if ((off64 + ((uint64_t)1 << 20)) >> 21) |
| @@ -889,7 +889,6 @@ struct TCCState { · 888 unmodified lines | ||
| 889 | 889 | |
| 890 | 890 | /* predefined sections */ |
| 891 | 891 | Section *text_section, *data_section, *rodata_section, *bss_section; |
| 892 | − Section *tdata_section, *tbss_section; | |
| 893 | 892 | Section *common_section; |
| 894 | 893 | Section *cur_text_section; /* current section where function code is generated */ |
| 895 | 894 | #ifdef CONFIG_TCC_BCHECK |
| @@ -930,6 +929,8 @@ struct TCCState { · 34 unmodified lines | ||
| 930 | 929 | ElfW_Rel *qrel; |
| 931 | 930 | #define qrel s1->qrel |
| 932 | 931 | |
| 932 | + addr_t tls_start, tls_end; | |
| 933 | + | |
| 933 | 934 | #ifdef TCC_TARGET_RISCV64 |
| 934 | 935 | struct pcrel_hi { addr_t addr, val; } **pcrel_hi_entries; |
| 935 | 936 | int nb_pcrel_hi_entries; |
| @@ -1979,8 +1980,6 @@ static inline void post_sem(TCCSem *p) { · 1043 unmodified lines | ||
| 1979 | 1980 | #define data_section TCC_STATE_VAR(data_section) |
| 1980 | 1981 | #define rodata_section TCC_STATE_VAR(rodata_section) |
| 1981 | 1982 | #define bss_section TCC_STATE_VAR(bss_section) |
| 1982 | −#define tdata_section TCC_STATE_VAR(tdata_section) | |
| 1983 | −#define tbss_section TCC_STATE_VAR(tbss_section) | |
| 1984 | 1983 | #define common_section TCC_STATE_VAR(common_section) |
| 1985 | 1984 | #define cur_text_section TCC_STATE_VAR(cur_text_section) |
| 1986 | 1985 | #define bounds_section TCC_STATE_VAR(bounds_section) |
| @@ -70,8 +70,6 @@ ST_FUNC void tccelf_new(TCCState *s) · 69 unmodified lines | ||
| 70 | 70 | /* create ro data section (make ro after relocation done with GNU_RELRO) */ |
| 71 | 71 | rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO); |
| 72 | 72 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); |
| 73 | − tdata_section = new_section(s, ".tdata", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE | SHF_TLS); | |
| 74 | − tbss_section = new_section(s, ".tbss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE | SHF_TLS); | |
| 75 | 73 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); |
| 76 | 74 | common_section->sh_num = SHN_COMMON; |
| 77 | 75 | |
| @@ -2198,12 +2196,11 @@ struct dyn_inf { · 2120 unmodified lines | ||
| 2198 | 2196 | ElfW(Phdr) *phdr; |
| 2199 | 2197 | int phnum; |
| 2200 | 2198 | int shnum; |
| 2199 | + int tls; | |
| 2200 | + int relro; | |
| 2201 | 2201 | Section *interp; |
| 2202 | 2202 | Section *note; |
| 2203 | 2203 | Section *gnu_hash; |
| 2204 | − | |
| 2205 | − /* read only segment mapping for GNU_RELRO */ | |
| 2206 | − Section _roinf, *roinf; | |
| 2207 | 2204 | }; |
| 2208 | 2205 | |
| 2209 | 2206 | /* Decide the layout of sections loaded in memory. This must be done before |
| @@ -2226,7 +2223,7 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 16 unmodified lines | ||
| 2226 | 2223 | if (s->sh_flags & SHF_WRITE) |
| 2227 | 2224 | j = 0x200; |
| 2228 | 2225 | if (s->sh_flags & SHF_TLS) |
| 2229 | − j += 0x200; | |
| 2226 | + j = 0x300; | |
| 2230 | 2227 | } else { |
| 2231 | 2228 | j = 0x700; |
| 2232 | 2229 | } |
| @@ -2287,6 +2284,9 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 54 unmodified lines | ||
| 2287 | 2284 | sec_order[0] = 0; |
| 2288 | 2285 | d->shnum = 1; |
| 2289 | 2286 | |
| 2287 | +#define SHFX_NEWPH (1 << 4) | |
| 2288 | +#define SHFX_RELRO (1 << 5) | |
| 2289 | + | |
| 2290 | 2290 | /* count PT_LOAD headers needed */ |
| 2291 | 2291 | n = f0 = 0; |
| 2292 | 2292 | for (i = 1; i < nb_sections; i++) { |
| @@ -2297,18 +2297,21 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 4 unmodified lines | ||
| 2297 | 2297 | ++d->shnum; |
| 2298 | 2298 | if (k < 0x700) { |
| 2299 | 2299 | f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR); |
| 2300 | −#if TARGETOS_NetBSD | |
| 2300 | +#if TARGETOS_NetBSD || TARGETOS_FreeBSD | |
| 2301 | 2301 | /* NetBSD only supports 2 PT_LOAD sections. |
| 2302 | 2302 | See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */ |
| 2303 | 2303 | if ((f & SHF_WRITE) == 0) |
| 2304 | 2304 | f |= SHF_EXECINSTR; |
| 2305 | 2305 | #else |
| 2306 | 2306 | if ((k & 0xfff0) == 0x240) /* RELRO sections */ |
| 2307 | − f |= 1<<4; | |
| 2307 | + d->relro = 1, f |= SHFX_RELRO; | |
| 2308 | 2308 | #endif |
| 2309 | 2309 | /* start new header when flags changed or relro, but avoid zero memsz */ |
| 2310 | 2310 | if (f != f0 && s->sh_size) |
| 2311 | − f0 = f, ++n, f |= 1<<8; | |
| 2311 | + f0 = f, ++n, f |= SHFX_NEWPH; | |
| 2312 | + | |
| 2313 | + if ((s->sh_flags & SHF_TLS) && s->sh_size) | |
| 2314 | + d->tls = 1, f |= SHF_TLS; | |
| 2312 | 2315 | } |
| 2313 | 2316 | sec_cls[i] = f; |
| 2314 | 2317 | //printf("ph %d sec %02d : %3X %3X %8.2X %04X %s\n", (f>0) * n, i, f, k, s->sh_type, (int)s->sh_size, s->name); |
| @@ -2331,13 +2334,24 @@ static ElfW(Phdr) *fill_phdr(ElfW(Phdr) *ph, int type, Section *s) · 16 unmodified lines | ||
| 2331 | 2334 | return ph; |
| 2332 | 2335 | } |
| 2333 | 2336 | |
| 2337 | +static ElfW(Phdr) *update_phdr(ElfW(Phdr) *ph, int type, Section *s, addr_t addr, int file_offset) | |
| 2338 | +{ | |
| 2339 | + if (ph->p_type == 0) { | |
| 2340 | + fill_phdr(ph, type, s); | |
| 2341 | + ph->p_flags |= PF_W; | |
| 2342 | + } | |
| 2343 | + ph->p_filesz = file_offset - ph->p_offset; | |
| 2344 | + ph->p_memsz = addr - ph->p_vaddr; | |
| 2345 | + return ph; | |
| 2346 | +} | |
| 2347 | + | |
| 2334 | 2348 | /* Assign sections to segments and decide how are sections laid out when loaded |
| 2335 | 2349 | in memory. This function also fills corresponding program headers. */ |
| 2336 | 2350 | static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) |
| 2337 | 2351 | { |
| 2338 | 2352 | Section *s; |
| 2339 | 2353 | addr_t addr, tmp, align, s_align, base; |
| 2340 | − ElfW(Phdr) *ph = NULL; | |
| 2354 | + ElfW(Phdr) *ph = NULL, *ph2; | |
| 2341 | 2355 | int i, f, n, phnum, phfill; |
| 2342 | 2356 | int file_offset; |
| 2343 | 2357 | |
| @@ -2347,26 +2361,16 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 3 unmodified lines | ||
| 2347 | 2361 | if (d->interp) |
| 2348 | 2362 | phfill = 2; |
| 2349 | 2363 | phnum += phfill; |
| 2364 | + if (d->tls) | |
| 2365 | + d->tls = phnum, ++phnum; | |
| 2366 | + if (d->relro) | |
| 2367 | + d->relro = phnum, ++phnum; | |
| 2350 | 2368 | if (d->note) |
| 2351 | 2369 | ++phnum; |
| 2352 | 2370 | if (d->dynamic) |
| 2353 | 2371 | ++phnum; |
| 2354 | 2372 | if (eh_frame_hdr_section) |
| 2355 | 2373 | ++phnum; |
| 2356 | − if (d->roinf) | |
| 2357 | − ++phnum; | |
| 2358 | − { | |
| 2359 | − int has_tls = 0; | |
| 2360 | − for (i = 1; i < s1->nb_sections; i++) { | |
| 2361 | − s = s1->sections[i]; | |
| 2362 | − if (s->sh_flags & SHF_TLS) { | |
| 2363 | − has_tls = 1; | |
| 2364 | − break; | |
| 2365 | − } | |
| 2366 | − } | |
| 2367 | − if (has_tls) | |
| 2368 | − ++phnum; | |
| 2369 | − } | |
| 2370 | 2374 | d->phnum = phnum; |
| 2371 | 2375 | d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); |
| 2372 | 2376 | |
| @@ -2415,7 +2419,7 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 42 unmodified lines | ||
| 2415 | 2419 | continue; |
| 2416 | 2420 | } |
| 2417 | 2421 | |
| 2418 | − if ((f & 1<<8) && n) { | |
| 2422 | + if ((f & SHFX_NEWPH) && n) { | |
| 2419 | 2423 | /* different rwx section flags */ |
| 2420 | 2424 | if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { |
| 2421 | 2425 | /* if in the middle of a page, w e duplicate the page in |
| @@ -2433,51 +2437,53 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 11 unmodified lines | ||
| 2433 | 2437 | s->sh_offset = file_offset; |
| 2434 | 2438 | s->sh_addr = addr; |
| 2435 | 2439 | |
| 2436 | − if (f & 1<<8) { | |
| 2440 | + addr += s->sh_size; | |
| 2441 | + if (s->sh_type != SHT_NOBITS) | |
| 2442 | + file_offset += s->sh_size; | |
| 2443 | + | |
| 2444 | + if (f & SHFX_NEWPH) { | |
| 2437 | 2445 | /* set new program header */ |
| 2438 | 2446 | ph = &d->phdr[phfill + n]; |
| 2439 | − ph->p_type = PT_LOAD; | |
| 2447 | + fill_phdr(ph, PT_LOAD, s); | |
| 2440 | 2448 | ph->p_align = s_align; |
| 2441 | − ph->p_flags = PF_R; | |
| 2442 | 2449 | if (f & SHF_WRITE) |
| 2443 | 2450 | ph->p_flags |= PF_W; |
| 2444 | 2451 | if (f & SHF_EXECINSTR) |
| 2445 | 2452 | ph->p_flags |= PF_X; |
| 2446 | − | |
| 2447 | − ph->p_offset = file_offset; | |
| 2448 | − ph->p_vaddr = addr; | |
| 2449 | 2453 | if (n == 0) { |
| 2450 | 2454 | /* Make the first PT_LOAD segment include the program |
| 2451 | 2455 | headers itself (and the ELF header as well), it'll |
| 2452 | 2456 | come out with same memory use but will make various |
| 2453 | 2457 | tools like binutils strip work better. */ |
| 2454 | 2458 | ph->p_offset = 0; |
| 2455 | − ph->p_vaddr = base; | |
| 2459 | + ph->p_paddr = ph->p_vaddr = base; | |
| 2456 | 2460 | } |
| 2457 | − ph->p_paddr = ph->p_vaddr; | |
| 2458 | 2461 | ++n; |
| 2459 | 2462 | } |
| 2460 | 2463 | |
| 2461 | − if (f & 1<<4) { | |
| 2462 | − Section *roinf = &d->_roinf; | |
| 2463 | − if (roinf->sh_size == 0) { | |
| 2464 | − roinf->sh_offset = s->sh_offset; | |
| 2465 | − roinf->sh_addr = s->sh_addr; | |
| 2466 | − roinf->sh_addralign = 1; | |
| 2467 | − } | |
| 2468 | − roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size; | |
| 2469 | − } | |
| 2464 | + if (ph) | |
| 2465 | + update_phdr(ph, 0, 0, addr, file_offset); | |
| 2470 | 2466 | |
| 2471 | − addr += s->sh_size; | |
| 2472 | − if (s->sh_type != SHT_NOBITS) | |
| 2473 | − file_offset += s->sh_size; | |
| 2467 | + if (f & SHFX_RELRO) { | |
| 2468 | + ph2 = update_phdr(&d->phdr[d->relro], PT_GNU_RELRO, s, addr, file_offset); | |
| 2469 | + ph2->p_align = 1; | |
| 2470 | + } | |
| 2474 | 2471 | |
| 2475 | − if (ph) { | |
| 2476 | − ph->p_filesz = file_offset - ph->p_offset; | |
| 2477 | − ph->p_memsz = addr - ph->p_vaddr; | |
| 2472 | + if (f & SHF_TLS) { | |
| 2473 | + ph2 = update_phdr(&d->phdr[d->tls], PT_TLS, s, addr, file_offset); | |
| 2474 | + if (s->sh_addralign > ph2->p_align) | |
| 2475 | + ph2->p_align = s->sh_addralign; | |
| 2478 | 2476 | } |
| 2479 | 2477 | } |
| 2480 | 2478 | |
| 2479 | + if (d->tls) { | |
| 2480 | + ++ph; | |
| 2481 | + /* for xxx-link.c:relocate() */ | |
| 2482 | + s1->tls_start = ph->p_vaddr; | |
| 2483 | + s1->tls_end = s1->tls_start + ph->p_memsz + (-ph->p_memsz & (ph->p_align - 1)); | |
| 2484 | + } | |
| 2485 | + if (d->relro) | |
| 2486 | + ++ph; | |
| 2481 | 2487 | /* Fill other headers */ |
| 2482 | 2488 | if (d->note) |
| 2483 | 2489 | fill_phdr(++ph, PT_NOTE, d->note); |
| @@ -2485,36 +2491,6 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 1 unmodified line | ||
| 2485 | 2491 | fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W; |
| 2486 | 2492 | if (eh_frame_hdr_section) |
| 2487 | 2493 | fill_phdr(++ph, PT_GNU_EH_FRAME, eh_frame_hdr_section); |
| 2488 | − if (d->roinf) | |
| 2489 | − fill_phdr(++ph, PT_GNU_RELRO, d->roinf)->p_flags |= PF_W; | |
| 2490 | − { | |
| 2491 | − /* Create PT_TLS segment covering all TLS sections */ | |
| 2492 | − Section *tls_start_sec = NULL; | |
| 2493 | − addr_t tls_start = 0, tls_end = 0; | |
| 2494 | − for (i = 1; i < s1->nb_sections; i++) { | |
| 2495 | − s = s1->sections[i]; | |
| 2496 | − if (s->sh_flags & SHF_TLS && s->sh_size) { | |
| 2497 | − if (!tls_start_sec) { | |
| 2498 | − tls_start_sec = s; | |
| 2499 | − tls_start = s->sh_addr; | |
| 2500 | − tls_end = s->sh_addr + s->sh_size; | |
| 2501 | − } else { | |
| 2502 | − if (s->sh_addr < tls_start) | |
| 2503 | − tls_start = s->sh_addr; | |
| 2504 | − if (s->sh_addr + s->sh_size > tls_end) | |
| 2505 | − tls_end = s->sh_addr + s->sh_size; | |
| 2506 | − } | |
| 2507 | − } | |
| 2508 | − } | |
| 2509 | − if (tls_start_sec) { | |
| 2510 | − ph = fill_phdr(++ph, PT_TLS, tls_start_sec); | |
| 2511 | − ph->p_vaddr = tls_start; | |
| 2512 | − ph->p_paddr = tls_start; | |
| 2513 | − ph->p_filesz = tls_end - tls_start; | |
| 2514 | − ph->p_memsz = ph->p_filesz; | |
| 2515 | − ph->p_align = tls_start_sec->sh_addralign; | |
| 2516 | − } | |
| 2517 | − } | |
| 2518 | 2494 | if (d->interp) |
| 2519 | 2495 | fill_phdr(&d->phdr[1], PT_INTERP, d->interp); |
| 2520 | 2496 | if (phfill) { |
| @@ -2823,7 +2799,7 @@ static void reorder_sections(TCCState *s1, int *sec_order) · 302 unmodified lines | ||
| 2823 | 2799 | |
| 2824 | 2800 | backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0])); |
| 2825 | 2801 | for (i = 0, nnew = 0, snew = NULL; i < s1->nb_sections; i++) { |
| 2826 | − k = sec_order[i]; | |
| 2802 | + k = sec_order ? sec_order[i] : i; | |
| 2827 | 2803 | s = s1->sections[k]; |
| 2828 | 2804 | if (!i || s->sh_name) { |
| 2829 | 2805 | backmap[k] = nnew; |
| @@ -2986,7 +2962,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 156 unmodified lines | ||
| 2986 | 2962 | ret = -1; |
| 2987 | 2963 | interp = dynstr = dynamic = NULL; |
| 2988 | 2964 | sec_order = NULL; |
| 2989 | − dyninf.roinf = &dyninf._roinf; | |
| 2990 | 2965 | |
| 2991 | 2966 | #ifdef TCC_TARGET_ARM |
| 2992 | 2967 | create_arm_attribute_section (s1); |
| @@ -3008,10 +2983,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 15 unmodified lines | ||
| 3008 | 2983 | dyninf.note = create_bsd_note_section (s1, ".note.tag", "FreeBSD"); |
| 3009 | 2984 | #endif |
| 3010 | 2985 | |
| 3011 | −#if TARGETOS_FreeBSD || TARGETOS_NetBSD | |
| 3012 | − dyninf.roinf = NULL; | |
| 3013 | −#endif | |
| 3014 | − | |
| 3015 | 2986 | /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ |
| 3016 | 2987 | tcc_add_runtime(s1); |
| 3017 | 2988 | resolve_common_syms(s1); |
| @@ -8400,10 +8400,9 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 8399 unmodified lines | ||
| 8400 | 8400 | while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY)) |
| 8401 | 8401 | tp = &tp->ref->type; |
| 8402 | 8402 | if (type->t & VT_TLS) { |
| 8403 | − if (has_init) | |
| 8404 | − sec = tdata_section; | |
| 8405 | − else | |
| 8406 | − sec = tbss_section; | |
| 8403 | + sec = find_section(tcc_state, has_init ? ".tdata" : ".tbss"); | |
| 8404 | + sec->sh_flags = SHF_ALLOC | SHF_WRITE | SHF_TLS; | |
| 8405 | + sec->sh_type = has_init ? SHT_PROGBITS : SHT_NOBITS; | |
| 8407 | 8406 | } else if (tp->t & VT_CONSTANT) { |
| 8408 | 8407 | sec = rodata_section; |
| 8409 | 8408 | } else if (has_init) { |
| @@ -57,8 +57,8 @@ endif · 56 unmodified lines | ||
| 57 | 57 | ifeq ($(CONFIG_OSX),yes) |
| 58 | 58 | SKIP += 144_tls.test # TLS runtime not supported on Mach-O |
| 59 | 59 | endif |
| 60 | −ifeq (,$(filter i386 x86_64 riscv64 arm64,$(ARCH))) | |
| 61 | − SKIP += 144_tls.test # TLS only implemented on these architectures so far | |
| 60 | +ifeq (-$(ARCH)-,-arm-) | |
| 61 | + SKIP += 144_tls.test # doesn't work currently | |
| 62 | 62 | endif |
| 63 | 63 | ifneq (-$(ARCH)-,-arm64-) |
| 64 | 64 | SKIP += 138_arm64_encoding.test |
| @@ -368,70 +368,29 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 367 unmodified lines | ||
| 368 | 368 | tcc_error_noabort("unexpected R_X86_64_TLSLD pattern"); |
| 369 | 369 | } |
| 370 | 370 | break; |
| 371 | + | |
| 371 | 372 | case R_X86_64_DTPOFF32: |
| 372 | 373 | case R_X86_64_TPOFF32: |
| 373 | − { | |
| 374 | − ElfW(Sym) *sym; | |
| 375 | − Section *sec; | |
| 376 | − int32_t x; | |
| 377 | − addr_t tls_start = 0, tls_end = 0, tls_align = 1; | |
| 378 | − int i; | |
| 379 | − | |
| 380 | − sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 381 | − sec = s1->sections[sym->st_shndx]; | |
| 382 | − | |
| 383 | − for (i = 1; i < s1->nb_sections; i++) { | |
| 384 | − Section *s = s1->sections[i]; | |
| 385 | − if (s->sh_flags & SHF_TLS && s->sh_size) { | |
| 386 | − if (!tls_start || s->sh_addr < tls_start) | |
| 387 | − tls_start = s->sh_addr; | |
| 388 | − if (s->sh_addr + s->sh_size > tls_end) | |
| 389 | − tls_end = s->sh_addr + s->sh_size; | |
| 390 | − if (s->sh_addralign > tls_align) | |
| 391 | − tls_align = s->sh_addralign; | |
| 392 | − } | |
| 393 | − } | |
| 394 | − if (tls_end > tls_start) { | |
| 395 | − addr_t tls_size = tls_end - tls_start; | |
| 396 | − addr_t aligned_size = (tls_size + tls_align - 1) & ~(tls_align - 1); | |
| 397 | − x = val - (tls_start + aligned_size); | |
| 398 | − } else { | |
| 399 | − x = val - sec->sh_addr - sec->data_offset; | |
| 400 | − } | |
| 401 | − add32le(ptr, x); | |
| 402 | − } | |
| 403 | − break; | |
| 404 | 374 | case R_X86_64_DTPOFF64: |
| 405 | 375 | case R_X86_64_TPOFF64: |
| 406 | 376 | { |
| 407 | − ElfW(Sym) *sym; | |
| 408 | − Section *sec; | |
| 409 | 377 | int32_t x; |
| 410 | − addr_t tls_start = 0, tls_end = 0, tls_align = 1; | |
| 411 | − int i; | |
| 412 | − | |
| 413 | − sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 414 | − sec = s1->sections[sym->st_shndx]; | |
| 415 | − | |
| 416 | − for (i = 1; i < s1->nb_sections; i++) { | |
| 417 | − Section *s = s1->sections[i]; | |
| 418 | − if (s->sh_flags & SHF_TLS && s->sh_size) { | |
| 419 | − if (!tls_start || s->sh_addr < tls_start) | |
| 420 | − tls_start = s->sh_addr; | |
| 421 | − if (s->sh_addr + s->sh_size > tls_end) | |
| 422 | − tls_end = s->sh_addr + s->sh_size; | |
| 423 | − if (s->sh_addralign > tls_align) | |
| 424 | − tls_align = s->sh_addralign; | |
| 425 | − } | |
| 426 | − } | |
| 427 | − if (tls_end > tls_start) { | |
| 428 | − addr_t tls_size = tls_end - tls_start; | |
| 429 | − addr_t aligned_size = (tls_size + tls_align - 1) & ~(tls_align - 1); | |
| 430 | − x = val - (tls_start + aligned_size); | |
| 378 | + if (s1->tls_end) { | |
| 379 | + x = val - s1->tls_end; | |
| 431 | 380 | } else { |
| 381 | + ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 382 | + Section *sec = s1->sections[sym->st_shndx]; | |
| 432 | 383 | x = val - sec->sh_addr - sec->data_offset; |
| 433 | 384 | } |
| 434 | − add64le(ptr, x); | |
| 385 | + switch (type) { | |
| 386 | + case R_X86_64_DTPOFF64: | |
| 387 | + case R_X86_64_TPOFF64: | |
| 388 | + add64le(ptr, x); | |
| 389 | + break; | |
| 390 | + default: | |
| 391 | + add32le(ptr, x); | |
| 392 | + break; | |
| 393 | + } | |
| 435 | 394 | } |
| 436 | 395 | break; |
| 437 | 396 | case R_X86_64_NONE: |