TLS bits
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86_64-win32 (push) Has been cancelled
build and test / test-i386-win32 (push) Has been cancelled
build and test / test-arm64-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled
build and test / test-i386-linux (push) Has been cancelled

tccelf.c:
- set_elf_sym()
    check NOBITS instead of just .bss
- sort_sections()
    must have common alignment for tls sections
    fix BSD relro

tccpe.c:
- sort .tbss after .tdata

tccrun.c:
- TLS not supported with -run
- arm64: FlushInstructionCache on win32 too

lib/bt-exe.c:
- use less unused bss memory (from global vars in tcc.h)

arm64-gen.c:
- arm64_sym():
  direct access (no GOT) for 'static' vars
  relocate with 'addend' unless GOT
- reserve X16/x17 for internal usage (specifically to avoid
  their usage as value register passed to store())
This commit is contained in:
grischka 2026-08-15 23:59:06 +02:00
parent 2ba12e83b3
commit 1bcec040d0
5 changed files with 99 additions and 93 deletions

View File

@ -77,14 +77,10 @@ ST_DATA const int reg_classes[NB_REGS] = {
RC_INT | RC_R(13), RC_INT | RC_R(13),
RC_INT | RC_R(14), RC_INT | RC_R(14),
RC_INT | RC_R(15), RC_INT | RC_R(15),
RC_INT | RC_R(16), RC_R(16), /* reserved for generator (arm64_sym()) */
RC_INT | RC_R(17), RC_R(17), /* reserved for generator (arm64_sym()) */
#ifdef TCC_TARGET_PE RC_R(18), /* reserved on Windows/OSX */
RC_R(18), /* (x18 reserved on Windows) */ RC_R30, /* not in RC_INT as we make special use of x30 */
#else
RC_INT | RC_R(18),
#endif
RC_R30, // not in RC_INT as we make special use of x30
RC_FLOAT | RC_F(0), RC_FLOAT | RC_F(0),
RC_FLOAT | RC_F(1), RC_FLOAT | RC_F(1),
RC_FLOAT | RC_F(2), RC_FLOAT | RC_F(2),
@ -298,6 +294,7 @@ static void arm64_spoff(int reg, uint64_t off)
static uint64_t arm64_check_offset(int sz_, uint64_t off) static uint64_t arm64_check_offset(int sz_, uint64_t off)
{ {
#ifndef TCC_TARGET_PE
uint32_t sz = sz_; uint32_t sz = sz_;
uint64_t scaled_mask = 0xffful << sz; uint64_t scaled_mask = 0xffful << sz;
if (!(off & ~scaled_mask) || (off < 256 || -off <= 256)) if (!(off & ~scaled_mask) || (off < 256 || -off <= 256))
@ -306,6 +303,7 @@ static uint64_t arm64_check_offset(int sz_, uint64_t off)
return scaled_mask; return scaled_mask;
if (off & 0x1fful) if (off & 0x1fful)
return 0x1fful; return 0x1fful;
#endif
return 0; return 0;
} }
@ -463,12 +461,17 @@ static void arm64_strv(int sz_, int dst, int bas, uint64_t off)
} }
} }
static void arm64_reloca(Sym *sym, int reloc_type, uint64_t addend)
{
greloca(cur_text_section, sym, ind, reloc_type, addend);
}
static void arm64_sym(int r, Sym *sym, addr_t addend) static void arm64_sym(int r, Sym *sym, addr_t addend)
{ {
if (sym->type.t & VT_TLS) { if (sym->type.t & VT_TLS) {
#if TCC_TARGET_PE #ifdef TCC_TARGET_PE
Sym *s2 = external_global_sym(TOK___tls_index, &int_type); Sym *s2 = external_global_sym(TOK___tls_index, &int_type);
int r2 = get_reg(RC_INT); int r2 = get_reg(RC_R(16));
arm64_sym(30, s2, 0); arm64_sym(30, s2, 0);
o(0xb94003de); // ldr w30, [x30] o(0xb94003de); // ldr w30, [x30]
o(0xf9402e40 | r2); // ldr r2, [x18, #88] o(0xf9402e40 | r2); // ldr r2, [x18, #88]
@ -477,46 +480,35 @@ static void arm64_sym(int r, Sym *sym, addr_t addend)
#else #else
o(0xd53bd040 | r); /* mrs xr, tpidr_el0 */ o(0xd53bd040 | r); /* mrs xr, tpidr_el0 */
#endif #endif
greloca(cur_text_section, sym, ind, R_AARCH64_TLSLE_ADD_TPREL_HI12, 0); arm64_reloca(sym, R_AARCH64_TLSLE_ADD_TPREL_HI12, addend);
/* add xr, xr, #0, lsl #12 */ o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) | ARM64_RN(r) | ARM64_RD(r)); /* add xr, xr, #0, lsl #12 */
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) | ARM64_RN(r) | ARM64_RD(r)); arm64_reloca(sym, R_AARCH64_TLSLE_ADD_TPREL_LO12, addend);
greloca(cur_text_section, sym, ind, R_AARCH64_TLSLE_ADD_TPREL_LO12, 0); o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(r) | ARM64_RD(r)); /* add xr, xr, #0 */
/* add xr, xr, #0 */ #ifndef TCC_TARGET_PE /* no elf-style GOT on Windows */
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(r) | ARM64_RD(r)); } else if (!(sym->type.t & VT_STATIC)) {
goto add_addend; arm64_reloca(sym, R_AARCH64_ADR_GOT_PAGE, 0);
} o(ARM64_ADRP | r); /* adrp xr, #sym */
#ifdef TCC_TARGET_PE arm64_reloca(sym, R_AARCH64_LD64_GOT_LO12_NC, 0);
/* PE links symbol addresses directly; there is no ELF-style GOT here. */ o(ARM64_LDR_X | ARM64_RN(r) | r); /* ld xr,[xr, #sym] */
greloca(cur_text_section, sym, ind, R_AARCH64_ADR_PREL_PG_HI21, 0); if (addend > 0xffffff) {
o(ARM64_ADRP | r); // adrp xr, #sym int t = get_reg(RC_R(16));
greloca(cur_text_section, sym, ind, R_AARCH64_ADD_ABS_LO12_NC, 0); arm64_movimm(t, addend); // use xt for addent
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(r) | r); // add xr, xr, #sym o(ARM64_ADD_REG | ARM64_SF(1) | ARM64_RM(t) | ARM64_RN(r) | r); /* add xr, xr, xt */
#else } else {
greloca(cur_text_section, sym, ind, R_AARCH64_ADR_GOT_PAGE, 0); if (addend & 0xfff) /* add xr, xr, #addend */
o(ARM64_ADRP | r); // adrp xr, #sym o(ARM64_ADD_IMM | ARM64_SF(1)
greloca(cur_text_section, sym, ind, R_AARCH64_LD64_GOT_LO12_NC, 0); | ARM64_RN(r) | r | (addend & 0xfff) << 10);
o(ARM64_LDR_X | ARM64_RN(r) | r); // ld xr,[xr, #sym] addend >>= 12;
#endif if (addend & 0xfff) /* add xr, xr, #addend, lsl #12 */
add_addend: o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1)
if (addend) { | ARM64_RN(r) | r | (addend & 0xfff) << 10);
// add xr, xr, #addend
if (addend & 0xffful)
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(r) | r |
(addend & 0xfff) << 10);
if (addend > 0xffful) {
// add xr, xr, #addend, lsl #12
if (addend & 0xfff000ul)
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) |
ARM64_RN(r) | r | ((addend >> 12) & 0xfff) << 10);
if (addend > 0xfffffful) {
/* very unlikely */
int t = r ? 0 : 1;
o(ARM64_STR_X_PRE | 0x001F0FE0U | t); /* str xt, [sp, #-16]! */
arm64_movimm(t, addend & ~0xffffffull); // use xt for addent
o(ARM64_ADD_REG | ARM64_SF(1) | ARM64_RM(t) | ARM64_RN(r) | r); /* add xr, xr, xt */
o(ARM64_LDR_X_POST | 0x000107E0U | t); /* ldr xt, [sp], #16 */
}
} }
#endif
} else {
arm64_reloca(sym, R_AARCH64_ADR_PREL_PG_HI21, addend);
o(ARM64_ADRP | r); /* adrp xr, #sym */
arm64_reloca(sym, R_AARCH64_ADD_ABS_LO12_NC, addend);
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(r) | r); /* add xr, xr, #sym */
} }
} }
@ -678,8 +670,8 @@ ST_FUNC void store(int r, SValue *sv)
static void arm64_gen_bl_or_b(int b) static void arm64_gen_bl_or_b(int b)
{ {
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM)) {
greloca(cur_text_section, vtop->sym, ind, arm64_reloca(vtop->sym,
b ? R_AARCH64_JUMP26 : R_AARCH64_CALL26, 0); b ? R_AARCH64_JUMP26 : R_AARCH64_CALL26, 0);
o(b ? ARM64_B : ARM64_BL); // b/bl . o(b ? ARM64_B : ARM64_BL); // b/bl .
} }
@ -691,16 +683,16 @@ static void arm64_gen_bl_or_b(int b)
} }
} }
#if defined(CONFIG_TCC_BCHECK) #if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE
static void gen_static_call(int v)
static void gen_bounds_call(int v)
{ {
Sym *sym = external_helper_sym(v); Sym *sym = external_helper_sym(v);
arm64_reloca(sym, R_AARCH64_CALL26, 0);
greloca(cur_text_section, sym, ind, R_AARCH64_CALL26, 0);
o(ARM64_BL); // bl o(ARM64_BL); // bl
} }
#endif
#if defined(CONFIG_TCC_BCHECK)
static void gen_bounds_prolog(void) static void gen_bounds_prolog(void)
{ {
/* leave some room for bound checking code */ /* leave some room for bound checking code */
@ -735,7 +727,7 @@ static void gen_bounds_epilog(void)
saved_ind = ind; saved_ind = ind;
ind = func_bound_ind; ind = func_bound_ind;
arm64_sym(0, sym_data, 0); arm64_sym(0, sym_data, 0);
gen_bounds_call(TOK___bound_local_new); gen_static_call(TOK___bound_local_new);
ind = saved_ind; ind = saved_ind;
} }
@ -743,7 +735,7 @@ static void gen_bounds_epilog(void)
o(0xa9bf07e0); /* stp x0, x1, [sp, #-16]! */ o(0xa9bf07e0); /* stp x0, x1, [sp, #-16]! */
o(0x3c9f0fe0); /* str q0, [sp, #-16]! */ o(0x3c9f0fe0); /* str q0, [sp, #-16]! */
arm64_sym(0, sym_data, 0); arm64_sym(0, sym_data, 0);
gen_bounds_call(TOK___bound_local_delete); gen_static_call(TOK___bound_local_delete);
o(0x3cc107e0); /* ldr q0, [sp], #16 */ o(0x3cc107e0); /* ldr q0, [sp], #16 */
o(0xa8c107e0); /* ldp x0, x1, [sp], #16 */ o(0xa8c107e0); /* ldp x0, x1, [sp], #16 */
} }
@ -1004,11 +996,8 @@ static void arm64_sub_sp(uint64_t diff)
return; return;
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
if (diff >= 4096) { if (diff >= 4096) {
Sym *sym = external_helper_sym(TOK___chkstk);
arm64_movimm(15, diff >> 4); arm64_movimm(15, diff >> 4);
greloca(cur_text_section, sym, ind, R_AARCH64_CALL26, 0); gen_static_call(TOK___chkstk);
o(ARM64_BL); // bl __chkstk
o(0xcb2f73ff); // sub sp,sp,x15,lsl #4 o(0xcb2f73ff); // sub sp,sp,x15,lsl #4
return; return;
} }

View File

@ -3,7 +3,7 @@
from tccrun.c into executables. */ from tccrun.c into executables. */
#define CONFIG_TCC_BACKTRACE_ONLY #define CONFIG_TCC_BACKTRACE_ONLY
#define ONE_SOURCE 1 #define ONE_SOURCE 0
#define pstrcpy tcc_pstrcpy #define pstrcpy tcc_pstrcpy
#include "../tccrun.c" #include "../tccrun.c"

View File

@ -693,6 +693,14 @@ version_add (TCCState *s1)
} }
#endif /* ndef ELF_OBJ_ONLY */ #endif /* ndef ELF_OBJ_ONLY */
/* catch .tbss also */
static int IS_BSS(TCCState *s1, int ndx)
{
return ndx == SHN_COMMON
|| (ndx < s1->nb_sections
&& s1->sections[ndx]->sh_type == SHT_NOBITS);
}
/* add an elf symbol : check if it is already defined and patch /* add an elf symbol : check if it is already defined and patch
it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
@ -744,13 +752,10 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
/* ignore hidden symbols after */ /* ignore hidden symbols after */
} else if (s->sh_flags & SHF_DYNSYM) { } else if (s->sh_flags & SHF_DYNSYM) {
/* we accept that two DLL define the same symbol */ /* we accept that two DLL define the same symbol */
} else if ((esym->st_shndx == SHN_COMMON } else if (!IS_BSS(s1, shndx) && IS_BSS(s1, esym->st_shndx)) {
|| esym->st_shndx == bss_section->sh_num)
&& (shndx < SHN_LORESERVE
&& shndx != bss_section->sh_num)) {
/* data symbol gets precedence over common/bss */ /* data symbol gets precedence over common/bss */
goto do_patch; goto do_patch;
} else if (shndx == SHN_COMMON || shndx == bss_section->sh_num) { } else if (IS_BSS(s1, shndx)) {
/* data symbol keeps precedence over common/bss */ /* data symbol keeps precedence over common/bss */
} else if (esym->st_other & ST_ASM_SET) { } else if (esym->st_other & ST_ASM_SET) {
/* If the existing symbol came from an asm .set /* If the existing symbol came from an asm .set
@ -2259,6 +2264,7 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
int i, j, k, f, f0, n; int i, j, k, f, f0, n;
int nb_sections = s1->nb_sections; int nb_sections = s1->nb_sections;
int *sec_cls = sec_order + nb_sections; int *sec_cls = sec_order + nb_sections;
int tls_align = 0; /* need common alignment for all tls sections */
for (i = 1; i < nb_sections; i++) { for (i = 1; i < nb_sections; i++) {
s = s1->sections[i]; s = s1->sections[i];
@ -2294,6 +2300,8 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
k = 0x60; k = 0x60;
/* RELRO sections --> */ /* RELRO sections --> */
} else if (s->sh_flags & SHF_TLS) { } else if (s->sh_flags & SHF_TLS) {
if (s->sh_addralign > tls_align)
tls_align = s->sh_addralign;
k = 0x40 + (s->sh_type == SHT_NOBITS); k = 0x40 + (s->sh_type == SHT_NOBITS);
} else if (s->sh_type == SHT_PREINIT_ARRAY) { } else if (s->sh_type == SHT_PREINIT_ARRAY) {
k = 0x42; k = 0x42;
@ -2302,11 +2310,11 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
} else if (s->sh_type == SHT_FINI_ARRAY) { } else if (s->sh_type == SHT_FINI_ARRAY) {
k = 0x44; k = 0x44;
} else if (s->sh_type == SHT_DYNAMIC) { } else if (s->sh_type == SHT_DYNAMIC) {
k = 0x46; k = 0x48;
} else if (s == s1->got) { } else if (s == s1->got) {
k = 0x47; /* .got as RELRO needs BIND_NOW in DT_FLAGS */ k = 0x49; /* .got as RELRO needs BIND_NOW in DT_FLAGS */
} else if (s->reloc && (s->reloc->sh_flags & SHF_ALLOC) && j == 0x100) { } else if (s->reloc && (s->reloc->sh_flags & SHF_ALLOC) && j == 0x100) {
k = 0x45; k = 0x45; /* +1 for data.ro */
/* <-- */ /* <-- */
} else if (s->sh_type == SHT_NOTE) { } else if (s->sh_type == SHT_NOTE) {
k = 0x08, d->notes = 1; k = 0x08, d->notes = 1;
@ -2349,15 +2357,18 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
/* NetBSD only supports 2 PT_LOAD sections. /* NetBSD only supports 2 PT_LOAD sections.
See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */ See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */
if ((f & SHF_WRITE) == 0) if ((f & SHF_WRITE) == 0)
f |= SHF_EXECINSTR, k = 0; /* no relro */ f |= SHF_EXECINSTR;
k = 0; /* no relro */
#endif #endif
if ((k & 0xfff0) == 0x240) /* RELRO sections */
d->relro = 1, f |= SHFX_RELRO;
/* start new header when flags changed, but avoid zero memsz */ /* start new header when flags changed, but avoid zero memsz */
if (f != f0 && s->sh_size) if (f != f0 && s->sh_size)
f0 = f, ++n, f |= SHFX_NEWPH; f0 = f, ++n, f |= SHFX_NEWPH;
if ((s->sh_flags & SHF_TLS) && s->sh_size) if ((s->sh_flags & SHF_TLS) && s->sh_size) {
s->sh_addralign = tls_align;
d->tls = 1, f |= SHF_TLS; d->tls = 1, f |= SHF_TLS;
if ((k & 0xfff0) == 0x240) /* RELRO sections */ }
d->relro = 1, f |= SHFX_RELRO;
} }
sec_cls[i] = f; sec_cls[i] = f;
//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); //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);
@ -2484,7 +2495,7 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
s->sh_offset = file_offset; s->sh_offset = file_offset;
s->sh_addr = addr; s->sh_addr = addr;
//printf("%d : %08x %08x %04x %03x %s\n", (int)(ph - d->phdr), (int)file_offset, (int)addr, (int)s->sh_size, s->sh_type, s->name); //printf("%d : %08x %08x %04x %03x %s %d\n", n, (int)file_offset, (int)addr, (int)s->sh_size, s->sh_type, s->name, align + 1);
addr += s->sh_size; addr += s->sh_size;
if (s->sh_type != SHT_NOBITS) if (s->sh_type != SHT_NOBITS)
file_offset += s->sh_size; file_offset += s->sh_size;
@ -2516,8 +2527,6 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
} }
if (f & SHF_TLS) { if (f & SHF_TLS) {
ph2 = update_phdr(&d->phdr[d->tls], PT_TLS, s, addr, file_offset); ph2 = update_phdr(&d->phdr[d->tls], PT_TLS, s, addr, file_offset);
if (s->sh_addralign > ph2->p_align)
ph2->p_align = s->sh_addralign;
if (s->sh_type == SHT_NOBITS) if (s->sh_type == SHT_NOBITS)
addr -= s->sh_size; addr -= s->sh_size;
/* for xxx-link.c:relocate() */ /* for xxx-link.c:relocate() */

26
tccpe.c
View File

@ -351,7 +351,8 @@ enum {
sec_bss , sec_bss ,
sec_idata , sec_idata ,
sec_pdata , sec_pdata ,
sec_tls , sec_tdata ,
sec_tbss ,
sec_other , sec_other ,
sec_rsrc , sec_rsrc ,
sec_debug , sec_debug ,
@ -1197,6 +1198,7 @@ static void pe_build_tls(struct pe_info *pe, Section *s)
int c, n; int c, n;
if (0 == s) { if (0 == s) {
pe->tls_size = sizeof (IMAGE_TLS_DIRECTORY);
pe->tls_dir = section_add(pe->thunk, pe->tls_size, 16); pe->tls_dir = section_add(pe->thunk, pe->tls_size, 16);
pe->tls_data = section_add(data_section, PTR_SIZE * (1+3), 16); pe->tls_data = section_add(data_section, PTR_SIZE * (1+3), 16);
/* put relocations on entries */ /* put relocations on entries */
@ -1209,6 +1211,7 @@ static void pe_build_tls(struct pe_info *pe, Section *s)
0, data_section->sh_num, "__tls_index"); 0, data_section->sh_num, "__tls_index");
return; return;
} }
if (0 == s1->tls_start) if (0 == s1->tls_start)
s1->tls_start = s->sh_addr; s1->tls_start = s->sh_addr;
d = (void*)(pe->thunk->data + pe->tls_dir); d = (void*)(pe->thunk->data + pe->tls_dir);
@ -1235,7 +1238,7 @@ static int pe_section_class(Section *s)
return sec_debug; return sec_debug;
} else if (flags & SHF_ALLOC) { } else if (flags & SHF_ALLOC) {
if (flags & SHF_TLS) if (flags & SHF_TLS)
return sec_tls; return sec_tdata + (type == SHT_NOBITS);
if (type == SHT_PROGBITS if (type == SHT_PROGBITS
|| type == SHT_INIT_ARRAY || type == SHT_INIT_ARRAY
|| type == SHT_FINI_ARRAY) { || type == SHT_FINI_ARRAY) {
@ -1273,6 +1276,7 @@ static int pe_assign_addresses (struct pe_info *pe)
if (PE_DLL == pe->type if (PE_DLL == pe->type
|| (s1->pe_dll_characteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)) || (s1->pe_dll_characteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE))
pe->reloc = new_section(s1, ".reloc", SHT_PROGBITS, 0); pe->reloc = new_section(s1, ".reloc", SHT_PROGBITS, 0);
pe->thunk = rodata_section;
//pe->thunk = new_section(s1, ".iedat", SHT_PROGBITS, SHF_ALLOC); //pe->thunk = new_section(s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
nbs = s1->nb_sections; nbs = s1->nb_sections;
@ -1284,35 +1288,30 @@ static int pe_assign_addresses (struct pe_info *pe)
for (n = i; n > 1 && k < (c = sec_cls[n - 1]); --n) for (n = i; n > 1 && k < (c = sec_cls[n - 1]); --n)
sec_cls[n] = c, sec_order[n] = sec_order[n - 1]; sec_cls[n] = c, sec_order[n] = sec_order[n - 1];
sec_cls[n] = k, sec_order[n] = i; sec_cls[n] = k, sec_order[n] = i;
if (k == sec_tls) if ((s->sh_flags & SHF_TLS) && 0 == pe->tls_size)
pe->tls_size = sizeof (IMAGE_TLS_DIRECTORY); pe_build_tls(pe, NULL);
} }
si = NULL; si = NULL;
addr = pe->imagebase + 1; addr = pe->imagebase + 1;
for (i = 1; (c = sec_cls[i]) < sec_last; ++i) { for (i = 1; (c = sec_cls[i]) < sec_last; ++i) {
s = s1->sections[sec_order[i]]; s = s1->sections[sec_order[i]];
if (PE_MERGE_DATA && c == sec_bss) if (PE_MERGE_DATA && c == sec_bss)
c = sec_data; c = sec_data;
if (c == sec_tbss)
c = sec_tdata;
if (si && c == si->cls && c != sec_debug) { if (si && c == si->cls && c != sec_debug) {
/* merge with previous section */ /* merge with previous section */
s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1; s->sh_addr = addr = ((addr - 1) | (s->sh_addralign - 1)) + 1;
} else { } else {
si = NULL; si = NULL;
s->sh_addr = addr = pe_virtual_align(pe, addr); s->sh_addr = addr = pe_virtual_align(pe, addr);
} }
if (NULL == pe->thunk
&& c == (data_section == rodata_section ? sec_data : sec_rdata))
pe->thunk = s;
if (s == pe->thunk) { if (s == pe->thunk) {
pe_build_imports(pe); pe_build_imports(pe);
pe_build_exports(pe); pe_build_exports(pe);
if (pe->tls_size)
pe_build_tls(pe, NULL);
} }
if (s == pe->reloc) if (s == pe->reloc)
@ -1367,7 +1366,7 @@ add_section:
Section *s = s1->sections[sec_order[i]]; Section *s = s1->sections[sec_order[i]];
int type = s->sh_type; int type = s->sh_type;
int flags = s->sh_flags; int flags = s->sh_flags;
printf("section %-16s %-10s %p %04x %s,%s,%s\n", printf("section %-16s %-10s %p %04x %2d %s,%s,%s\n",
s->name, s->name,
type == SHT_PROGBITS ? "progbits" : type == SHT_PROGBITS ? "progbits" :
type == SHT_INIT_ARRAY ? "initarr" : type == SHT_INIT_ARRAY ? "initarr" :
@ -1378,6 +1377,7 @@ add_section:
type == SHT_RELX ? "rel" : "???", type == SHT_RELX ? "rel" : "???",
s->sh_addr, s->sh_addr,
(unsigned)s->data_offset, (unsigned)s->data_offset,
s->sh_addralign,
flags & SHF_ALLOC ? "alloc" : "", flags & SHF_ALLOC ? "alloc" : "",
flags & SHF_WRITE ? "write" : "", flags & SHF_WRITE ? "write" : "",
flags & SHF_EXECINSTR ? "exec" : "" flags & SHF_EXECINSTR ? "exec" : ""

View File

@ -385,6 +385,9 @@ redo:
continue; continue;
} }
if ((s->sh_flags & SHF_TLS) && length)
return tcc_error_noabort("thread-local storage not supported with -run");
align = s->sh_addralign; align = s->sh_addralign;
if (++n == 1) { if (++n == 1) {
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
@ -486,13 +489,18 @@ static int protect_pages(void *ptr, unsigned long length, int mode)
}; };
if (mprotect(ptr, length, protect[mode])) if (mprotect(ptr, length, protect[mode]))
return -1; return -1;
#endif
/* XXX: BSD sometimes dump core with bad system call */ /* XXX: BSD sometimes dump core with bad system call */
# if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 #if (defined TCC_TARGET_ARM && !TARGETOS_BSD) \
|| defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
if (mode == 0 || mode == 3) { if (mode == 0 || mode == 3) {
#ifdef _WIN32
FlushInstructionCache(GetCurrentProcess(), ptr, length);
#else
void __clear_cache(void *beginning, void *end); void __clear_cache(void *beginning, void *end);
__clear_cache(ptr, (char *)ptr + length); __clear_cache(ptr, (char *)ptr + length);
#endif
} }
# endif
#endif #endif
return 0; return 0;
} }