| @@ -70,8 +70,6 @@ ST_FUNC void tccelf_new(TCCState *s) · 69 unmodified lines |
| 70 | /* create ro data section (make ro after relocation done with GNU_RELRO) */ | 70 | /* create ro data section (make ro after relocation done with GNU_RELRO) */ |
| 71 | rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO); | 71 | rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO); |
| 72 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); | 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 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); | 73 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); |
| 76 | common_section->sh_num = SHN_COMMON; | 74 | common_section->sh_num = SHN_COMMON; |
| 77 | | 75 | |
| @@ -2198,12 +2196,11 @@ struct dyn_inf { · 2120 unmodified lines |
| 2198 | ElfW(Phdr) *phdr; | 2196 | ElfW(Phdr) *phdr; |
| 2199 | int phnum; | 2197 | int phnum; |
| 2200 | int shnum; | 2198 | int shnum; |
| | 2199 | int tls; |
| | 2200 | int relro; |
| 2201 | Section *interp; | 2201 | Section *interp; |
| 2202 | Section *note; | 2202 | Section *note; |
| 2203 | Section *gnu_hash; | 2203 | Section *gnu_hash; |
| 2204 | | | |
| 2205 | /* read only segment mapping for GNU_RELRO */ | | |
| 2206 | Section _roinf, *roinf; | | |
| 2207 | }; | 2204 | }; |
| 2208 | | 2205 | |
| 2209 | /* Decide the layout of sections loaded in memory. This must be done before | 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 | if (s->sh_flags & SHF_WRITE) | 2223 | if (s->sh_flags & SHF_WRITE) |
| 2227 | j = 0x200; | 2224 | j = 0x200; |
| 2228 | if (s->sh_flags & SHF_TLS) | 2225 | if (s->sh_flags & SHF_TLS) |
| 2229 | j += 0x200; | 2226 | j = 0x300; |
| 2230 | } else { | 2227 | } else { |
| 2231 | j = 0x700; | 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 | sec_order[0] = 0; | 2284 | sec_order[0] = 0; |
| 2288 | d->shnum = 1; | 2285 | d->shnum = 1; |
| 2289 | | 2286 | |
| | 2287 | #define SHFX_NEWPH (1 << 4) |
| | 2288 | #define SHFX_RELRO (1 << 5) |
| | 2289 | |
| 2290 | /* count PT_LOAD headers needed */ | 2290 | /* count PT_LOAD headers needed */ |
| 2291 | n = f0 = 0; | 2291 | n = f0 = 0; |
| 2292 | for (i = 1; i < nb_sections; i++) { | 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 | ++d->shnum; | 2297 | ++d->shnum; |
| 2298 | if (k < 0x700) { | 2298 | if (k < 0x700) { |
| 2299 | f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR); | 2299 | f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR); |
| 2300 | #if TARGETOS_NetBSD | 2300 | #if TARGETOS_NetBSD || TARGETOS_FreeBSD |
| 2301 | /* NetBSD only supports 2 PT_LOAD sections. | 2301 | /* NetBSD only supports 2 PT_LOAD sections. |
| 2302 | See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */ | 2302 | See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */ |
| 2303 | if ((f & SHF_WRITE) == 0) | 2303 | if ((f & SHF_WRITE) == 0) |
| 2304 | f |= SHF_EXECINSTR; | 2304 | f |= SHF_EXECINSTR; |
| 2305 | #else | 2305 | #else |
| 2306 | if ((k & 0xfff0) == 0x240) /* RELRO sections */ | 2306 | if ((k & 0xfff0) == 0x240) /* RELRO sections */ |
| 2307 | f |= 1<<4; | 2307 | d->relro = 1, f |= SHFX_RELRO; |
| 2308 | #endif | 2308 | #endif |
| 2309 | /* start new header when flags changed or relro, but avoid zero memsz */ | 2309 | /* start new header when flags changed or relro, but avoid zero memsz */ |
| 2310 | if (f != f0 && s->sh_size) | 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 | sec_cls[i] = f; | 2316 | sec_cls[i] = f; |
| 2314 | //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); | 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 | return ph; | 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 | /* Assign sections to segments and decide how are sections laid out when loaded | 2348 | /* Assign sections to segments and decide how are sections laid out when loaded |
| 2335 | in memory. This function also fills corresponding program headers. */ | 2349 | in memory. This function also fills corresponding program headers. */ |
| 2336 | static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) | 2350 | static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) |
| 2337 | { | 2351 | { |
| 2338 | Section *s; | 2352 | Section *s; |
| 2339 | addr_t addr, tmp, align, s_align, base; | 2353 | addr_t addr, tmp, align, s_align, base; |
| 2340 | ElfW(Phdr) *ph = NULL; | 2354 | ElfW(Phdr) *ph = NULL, *ph2; |
| 2341 | int i, f, n, phnum, phfill; | 2355 | int i, f, n, phnum, phfill; |
| 2342 | int file_offset; | 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 | if (d->interp) | 2361 | if (d->interp) |
| 2348 | phfill = 2; | 2362 | phfill = 2; |
| 2349 | phnum += phfill; | 2363 | phnum += phfill; |
| | 2364 | if (d->tls) |
| | 2365 | d->tls = phnum, ++phnum; |
| | 2366 | if (d->relro) |
| | 2367 | d->relro = phnum, ++phnum; |
| 2350 | if (d->note) | 2368 | if (d->note) |
| 2351 | ++phnum; | 2369 | ++phnum; |
| 2352 | if (d->dynamic) | 2370 | if (d->dynamic) |
| 2353 | ++phnum; | 2371 | ++phnum; |
| 2354 | if (eh_frame_hdr_section) | 2372 | if (eh_frame_hdr_section) |
| 2355 | ++phnum; | 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 | d->phnum = phnum; | 2374 | d->phnum = phnum; |
| 2371 | d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); | 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 | continue; | 2419 | continue; |
| 2416 | } | 2420 | } |
| 2417 | | 2421 | |
| 2418 | if ((f & 1<<8) && n) { | 2422 | if ((f & SHFX_NEWPH) && n) { |
| 2419 | /* different rwx section flags */ | 2423 | /* different rwx section flags */ |
| 2420 | if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { | 2424 | if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { |
| 2421 | /* if in the middle of a page, w e duplicate the page in | 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 | s->sh_offset = file_offset; | 2437 | s->sh_offset = file_offset; |
| 2434 | s->sh_addr = addr; | 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 | /* set new program header */ | 2445 | /* set new program header */ |
| 2438 | ph = &d->phdr[phfill + n]; | 2446 | ph = &d->phdr[phfill + n]; |
| 2439 | ph->p_type = PT_LOAD; | 2447 | fill_phdr(ph, PT_LOAD, s); |
| 2440 | ph->p_align = s_align; | 2448 | ph->p_align = s_align; |
| 2441 | ph->p_flags = PF_R; | | |
| 2442 | if (f & SHF_WRITE) | 2449 | if (f & SHF_WRITE) |
| 2443 | ph->p_flags |= PF_W; | 2450 | ph->p_flags |= PF_W; |
| 2444 | if (f & SHF_EXECINSTR) | 2451 | if (f & SHF_EXECINSTR) |
| 2445 | ph->p_flags |= PF_X; | 2452 | ph->p_flags |= PF_X; |
| 2446 | | | |
| 2447 | ph->p_offset = file_offset; | | |
| 2448 | ph->p_vaddr = addr; | | |
| 2449 | if (n == 0) { | 2453 | if (n == 0) { |
| 2450 | /* Make the first PT_LOAD segment include the program | 2454 | /* Make the first PT_LOAD segment include the program |
| 2451 | headers itself (and the ELF header as well), it'll | 2455 | headers itself (and the ELF header as well), it'll |
| 2452 | come out with same memory use but will make various | 2456 | come out with same memory use but will make various |
| 2453 | tools like binutils strip work better. */ | 2457 | tools like binutils strip work better. */ |
| 2454 | ph->p_offset = 0; | 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 | ++n; | 2461 | ++n; |
| 2459 | } | 2462 | } |
| 2460 | | 2463 | |
| 2461 | if (f & 1<<4) { | 2464 | if (ph) |
| 2462 | Section *roinf = &d->_roinf; | 2465 | update_phdr(ph, 0, 0, addr, file_offset); |
| 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 | } | | |
| 2470 | | 2466 | |
| 2471 | addr += s->sh_size; | 2467 | if (f & SHFX_RELRO) { |
| 2472 | if (s->sh_type != SHT_NOBITS) | 2468 | ph2 = update_phdr(&d->phdr[d->relro], PT_GNU_RELRO, s, addr, file_offset); |
| 2473 | file_offset += s->sh_size; | 2469 | ph2->p_align = 1; |
| | 2470 | } |
| 2474 | | 2471 | |
| 2475 | if (ph) { | 2472 | if (f & SHF_TLS) { |
| 2476 | ph->p_filesz = file_offset - ph->p_offset; | 2473 | ph2 = update_phdr(&d->phdr[d->tls], PT_TLS, s, addr, file_offset); |
| 2477 | ph->p_memsz = addr - ph->p_vaddr; | 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 | /* Fill other headers */ | 2487 | /* Fill other headers */ |
| 2482 | if (d->note) | 2488 | if (d->note) |
| 2483 | fill_phdr(++ph, PT_NOTE, d->note); | 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 | fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W; | 2491 | fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W; |
| 2486 | if (eh_frame_hdr_section) | 2492 | if (eh_frame_hdr_section) |
| 2487 | fill_phdr(++ph, PT_GNU_EH_FRAME, eh_frame_hdr_section); | 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 | if (d->interp) | 2494 | if (d->interp) |
| 2519 | fill_phdr(&d->phdr[1], PT_INTERP, d->interp); | 2495 | fill_phdr(&d->phdr[1], PT_INTERP, d->interp); |
| 2520 | if (phfill) { | 2496 | if (phfill) { |
| @@ -2823,7 +2799,7 @@ static void reorder_sections(TCCState *s1, int *sec_order) · 302 unmodified lines |
| 2823 | | 2799 | |
| 2824 | backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0])); | 2800 | backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0])); |
| 2825 | for (i = 0, nnew = 0, snew = NULL; i < s1->nb_sections; i++) { | 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 | s = s1->sections[k]; | 2803 | s = s1->sections[k]; |
| 2828 | if (!i || s->sh_name) { | 2804 | if (!i || s->sh_name) { |
| 2829 | backmap[k] = nnew; | 2805 | backmap[k] = nnew; |
| @@ -2986,7 +2962,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 156 unmodified lines |
| 2986 | ret = -1; | 2962 | ret = -1; |
| 2987 | interp = dynstr = dynamic = NULL; | 2963 | interp = dynstr = dynamic = NULL; |
| 2988 | sec_order = NULL; | 2964 | sec_order = NULL; |
| 2989 | dyninf.roinf = &dyninf._roinf; | | |
| 2990 | | 2965 | |
| 2991 | #ifdef TCC_TARGET_ARM | 2966 | #ifdef TCC_TARGET_ARM |
| 2992 | create_arm_attribute_section (s1); | 2967 | create_arm_attribute_section (s1); |
| @@ -3008,10 +2983,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 15 unmodified lines |
| 3008 | dyninf.note = create_bsd_note_section (s1, ".note.tag", "FreeBSD"); | 2983 | dyninf.note = create_bsd_note_section (s1, ".note.tag", "FreeBSD"); |
| 3009 | #endif | 2984 | #endif |
| 3010 | | 2985 | |
| 3011 | #if TARGETOS_FreeBSD || TARGETOS_NetBSD | | |
| 3012 | dyninf.roinf = NULL; | | |
| 3013 | #endif | | |
| 3014 | | | |
| 3015 | /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ | 2986 | /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ |
| 3016 | tcc_add_runtime(s1); | 2987 | tcc_add_runtime(s1); |
| 3017 | resolve_common_syms(s1); | 2988 | resolve_common_syms(s1); |