mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-10 21:38:47 +08:00
review generic tls support
*-link.c: remove stupid loops tccelf.c: ...also tccgen.c: create .tdata/.tbss sections only when needed
This commit is contained in:
parent
7f7845cd7e
commit
5673055a9c
25
arm-link.c
25
arm-link.c
@ -434,29 +434,12 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
return;
|
return;
|
||||||
case R_ARM_TLS_LE32:
|
case R_ARM_TLS_LE32:
|
||||||
{
|
{
|
||||||
ElfW(Sym) *sym;
|
|
||||||
Section *sec;
|
|
||||||
int32_t x;
|
int32_t x;
|
||||||
addr_t tls_start = 0, tls_end = 0, tls_align = 1;
|
if (s1->tls_end) {
|
||||||
int i;
|
x = val - s1->tls_start + 8;
|
||||||
|
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
sec = s1->sections[sym->st_shndx];
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
Section *s = s1->sections[i];
|
|
||||||
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
|
||||||
if (!tls_start || s->sh_addr < tls_start)
|
|
||||||
tls_start = s->sh_addr;
|
|
||||||
if (s->sh_addr + s->sh_size > tls_end)
|
|
||||||
tls_end = s->sh_addr + s->sh_size;
|
|
||||||
if (s->sh_addralign > tls_align)
|
|
||||||
tls_align = s->sh_addralign;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tls_end > tls_start) {
|
|
||||||
x = val - tls_start + 8;
|
|
||||||
} else {
|
} else {
|
||||||
|
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
Section *sec = s1->sections[sym->st_shndx];
|
||||||
x = val - sec->sh_addr - sec->data_offset + 8;
|
x = val - sec->sh_addr - sec->data_offset + 8;
|
||||||
}
|
}
|
||||||
add32le(ptr, x);
|
add32le(ptr, x);
|
||||||
|
|||||||
11
arm64-link.c
11
arm64-link.c
@ -371,17 +371,8 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
return;
|
return;
|
||||||
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||||
case R_AARCH64_TLSLE_ADD_TPREL_LO12: {
|
case R_AARCH64_TLSLE_ADD_TPREL_LO12: {
|
||||||
addr_t tls_start = 0;
|
|
||||||
int i;
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
Section *s = s1->sections[i];
|
|
||||||
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
|
||||||
if (!tls_start || s->sh_addr < tls_start)
|
|
||||||
tls_start = s->sh_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* glibc arm64: tp points to tcbhead_t (DTV), TLS data starts after it */
|
/* glibc arm64: tp points to tcbhead_t (DTV), TLS data starts after it */
|
||||||
int64_t tp_offset = val - tls_start + 16;
|
int64_t tp_offset = val - s1->tls_start + 16;
|
||||||
int64_t imm;
|
int64_t imm;
|
||||||
if (type == R_AARCH64_TLSLE_ADD_TPREL_HI12)
|
if (type == R_AARCH64_TLSLE_ADD_TPREL_HI12)
|
||||||
imm = (tp_offset >> 12) & 0xfff;
|
imm = (tp_offset >> 12) & 0xfff;
|
||||||
|
|||||||
27
i386-link.c
27
i386-link.c
@ -318,31 +318,12 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
return;
|
return;
|
||||||
case R_386_TLS_LE:
|
case R_386_TLS_LE:
|
||||||
{
|
{
|
||||||
ElfW(Sym) *sym;
|
|
||||||
Section *sec;
|
|
||||||
int32_t x;
|
int32_t x;
|
||||||
addr_t tls_start = 0, tls_end = 0, tls_align = 1;
|
if (s1->tls_end) {
|
||||||
int i;
|
x = val - s1->tls_end;
|
||||||
|
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
sec = s1->sections[sym->st_shndx];
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
Section *s = s1->sections[i];
|
|
||||||
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
|
||||||
if (!tls_start || s->sh_addr < tls_start)
|
|
||||||
tls_start = s->sh_addr;
|
|
||||||
if (s->sh_addr + s->sh_size > tls_end)
|
|
||||||
tls_end = s->sh_addr + s->sh_size;
|
|
||||||
if (s->sh_addralign > tls_align)
|
|
||||||
tls_align = s->sh_addralign;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tls_end > tls_start) {
|
|
||||||
addr_t tls_size = tls_end - tls_start;
|
|
||||||
addr_t aligned_size = (tls_size + tls_align - 1) & ~(tls_align - 1);
|
|
||||||
x = val - (tls_start + aligned_size);
|
|
||||||
} else {
|
} else {
|
||||||
|
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
Section *sec = s1->sections[sym->st_shndx];
|
||||||
x = val - sec->sh_addr - sec->data_offset;
|
x = val - sec->sh_addr - sec->data_offset;
|
||||||
}
|
}
|
||||||
add32le(ptr, x);
|
add32le(ptr, x);
|
||||||
|
|||||||
@ -407,17 +407,7 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
|
|
||||||
case R_RISCV_TPREL_HI20:
|
case R_RISCV_TPREL_HI20:
|
||||||
case R_RISCV_TPREL_LO12_I: {
|
case R_RISCV_TPREL_LO12_I: {
|
||||||
addr_t tls_start = 0;
|
int64_t tp_offset = val - s1->tls_start;
|
||||||
int64_t tp_offset;
|
|
||||||
int i;
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
Section *s = s1->sections[i];
|
|
||||||
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
|
||||||
if (!tls_start || s->sh_addr < tls_start)
|
|
||||||
tls_start = s->sh_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tp_offset = val - tls_start;
|
|
||||||
if (type == R_RISCV_TPREL_HI20) {
|
if (type == R_RISCV_TPREL_HI20) {
|
||||||
off64 = (int64_t)(tp_offset + 0x800) >> 12;
|
off64 = (int64_t)(tp_offset + 0x800) >> 12;
|
||||||
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
||||||
|
|||||||
5
tcc.h
5
tcc.h
@ -889,7 +889,6 @@ struct TCCState {
|
|||||||
|
|
||||||
/* predefined sections */
|
/* predefined sections */
|
||||||
Section *text_section, *data_section, *rodata_section, *bss_section;
|
Section *text_section, *data_section, *rodata_section, *bss_section;
|
||||||
Section *tdata_section, *tbss_section;
|
|
||||||
Section *common_section;
|
Section *common_section;
|
||||||
Section *cur_text_section; /* current section where function code is generated */
|
Section *cur_text_section; /* current section where function code is generated */
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
@ -930,6 +929,8 @@ struct TCCState {
|
|||||||
ElfW_Rel *qrel;
|
ElfW_Rel *qrel;
|
||||||
#define qrel s1->qrel
|
#define qrel s1->qrel
|
||||||
|
|
||||||
|
addr_t tls_start, tls_end;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_RISCV64
|
#ifdef TCC_TARGET_RISCV64
|
||||||
struct pcrel_hi { addr_t addr, val; } **pcrel_hi_entries;
|
struct pcrel_hi { addr_t addr, val; } **pcrel_hi_entries;
|
||||||
int nb_pcrel_hi_entries;
|
int nb_pcrel_hi_entries;
|
||||||
@ -1979,8 +1980,6 @@ static inline void post_sem(TCCSem *p) {
|
|||||||
#define data_section TCC_STATE_VAR(data_section)
|
#define data_section TCC_STATE_VAR(data_section)
|
||||||
#define rodata_section TCC_STATE_VAR(rodata_section)
|
#define rodata_section TCC_STATE_VAR(rodata_section)
|
||||||
#define bss_section TCC_STATE_VAR(bss_section)
|
#define bss_section TCC_STATE_VAR(bss_section)
|
||||||
#define tdata_section TCC_STATE_VAR(tdata_section)
|
|
||||||
#define tbss_section TCC_STATE_VAR(tbss_section)
|
|
||||||
#define common_section TCC_STATE_VAR(common_section)
|
#define common_section TCC_STATE_VAR(common_section)
|
||||||
#define cur_text_section TCC_STATE_VAR(cur_text_section)
|
#define cur_text_section TCC_STATE_VAR(cur_text_section)
|
||||||
#define bounds_section TCC_STATE_VAR(bounds_section)
|
#define bounds_section TCC_STATE_VAR(bounds_section)
|
||||||
|
|||||||
139
tccelf.c
139
tccelf.c
@ -70,8 +70,6 @@ ST_FUNC void tccelf_new(TCCState *s)
|
|||||||
/* create ro data section (make ro after relocation done with GNU_RELRO) */
|
/* create ro data section (make ro after relocation done with GNU_RELRO) */
|
||||||
rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO);
|
rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO);
|
||||||
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
|
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
|
||||||
tdata_section = new_section(s, ".tdata", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE | SHF_TLS);
|
|
||||||
tbss_section = new_section(s, ".tbss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE | SHF_TLS);
|
|
||||||
common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
|
common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
|
||||||
common_section->sh_num = SHN_COMMON;
|
common_section->sh_num = SHN_COMMON;
|
||||||
|
|
||||||
@ -2198,12 +2196,11 @@ struct dyn_inf {
|
|||||||
ElfW(Phdr) *phdr;
|
ElfW(Phdr) *phdr;
|
||||||
int phnum;
|
int phnum;
|
||||||
int shnum;
|
int shnum;
|
||||||
|
int tls;
|
||||||
|
int relro;
|
||||||
Section *interp;
|
Section *interp;
|
||||||
Section *note;
|
Section *note;
|
||||||
Section *gnu_hash;
|
Section *gnu_hash;
|
||||||
|
|
||||||
/* read only segment mapping for GNU_RELRO */
|
|
||||||
Section _roinf, *roinf;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Decide the layout of sections loaded in memory. This must be done before
|
/* 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)
|
|||||||
if (s->sh_flags & SHF_WRITE)
|
if (s->sh_flags & SHF_WRITE)
|
||||||
j = 0x200;
|
j = 0x200;
|
||||||
if (s->sh_flags & SHF_TLS)
|
if (s->sh_flags & SHF_TLS)
|
||||||
j += 0x200;
|
j = 0x300;
|
||||||
} else {
|
} else {
|
||||||
j = 0x700;
|
j = 0x700;
|
||||||
}
|
}
|
||||||
@ -2287,6 +2284,9 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
|||||||
sec_order[0] = 0;
|
sec_order[0] = 0;
|
||||||
d->shnum = 1;
|
d->shnum = 1;
|
||||||
|
|
||||||
|
#define SHFX_NEWPH (1 << 4)
|
||||||
|
#define SHFX_RELRO (1 << 5)
|
||||||
|
|
||||||
/* count PT_LOAD headers needed */
|
/* count PT_LOAD headers needed */
|
||||||
n = f0 = 0;
|
n = f0 = 0;
|
||||||
for (i = 1; i < nb_sections; i++) {
|
for (i = 1; i < nb_sections; i++) {
|
||||||
@ -2297,18 +2297,21 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
|||||||
++d->shnum;
|
++d->shnum;
|
||||||
if (k < 0x700) {
|
if (k < 0x700) {
|
||||||
f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR);
|
f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR);
|
||||||
#if TARGETOS_NetBSD
|
#if TARGETOS_NetBSD || TARGETOS_FreeBSD
|
||||||
/* 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;
|
f |= SHF_EXECINSTR;
|
||||||
#else
|
#else
|
||||||
if ((k & 0xfff0) == 0x240) /* RELRO sections */
|
if ((k & 0xfff0) == 0x240) /* RELRO sections */
|
||||||
f |= 1<<4;
|
d->relro = 1, f |= SHFX_RELRO;
|
||||||
#endif
|
#endif
|
||||||
/* start new header when flags changed or relro, but avoid zero memsz */
|
/* start new header when flags changed or relro, but avoid zero memsz */
|
||||||
if (f != f0 && s->sh_size)
|
if (f != f0 && s->sh_size)
|
||||||
f0 = f, ++n, f |= 1<<8;
|
f0 = f, ++n, f |= SHFX_NEWPH;
|
||||||
|
|
||||||
|
if ((s->sh_flags & SHF_TLS) && s->sh_size)
|
||||||
|
d->tls = 1, f |= SHF_TLS;
|
||||||
}
|
}
|
||||||
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);
|
||||||
@ -2331,13 +2334,24 @@ static ElfW(Phdr) *fill_phdr(ElfW(Phdr) *ph, int type, Section *s)
|
|||||||
return ph;
|
return ph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ElfW(Phdr) *update_phdr(ElfW(Phdr) *ph, int type, Section *s, addr_t addr, int file_offset)
|
||||||
|
{
|
||||||
|
if (ph->p_type == 0) {
|
||||||
|
fill_phdr(ph, type, s);
|
||||||
|
ph->p_flags |= PF_W;
|
||||||
|
}
|
||||||
|
ph->p_filesz = file_offset - ph->p_offset;
|
||||||
|
ph->p_memsz = addr - ph->p_vaddr;
|
||||||
|
return ph;
|
||||||
|
}
|
||||||
|
|
||||||
/* Assign sections to segments and decide how are sections laid out when loaded
|
/* Assign sections to segments and decide how are sections laid out when loaded
|
||||||
in memory. This function also fills corresponding program headers. */
|
in memory. This function also fills corresponding program headers. */
|
||||||
static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
addr_t addr, tmp, align, s_align, base;
|
addr_t addr, tmp, align, s_align, base;
|
||||||
ElfW(Phdr) *ph = NULL;
|
ElfW(Phdr) *ph = NULL, *ph2;
|
||||||
int i, f, n, phnum, phfill;
|
int i, f, n, phnum, phfill;
|
||||||
int file_offset;
|
int file_offset;
|
||||||
|
|
||||||
@ -2347,26 +2361,16 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
|||||||
if (d->interp)
|
if (d->interp)
|
||||||
phfill = 2;
|
phfill = 2;
|
||||||
phnum += phfill;
|
phnum += phfill;
|
||||||
|
if (d->tls)
|
||||||
|
d->tls = phnum, ++phnum;
|
||||||
|
if (d->relro)
|
||||||
|
d->relro = phnum, ++phnum;
|
||||||
if (d->note)
|
if (d->note)
|
||||||
++phnum;
|
++phnum;
|
||||||
if (d->dynamic)
|
if (d->dynamic)
|
||||||
++phnum;
|
++phnum;
|
||||||
if (eh_frame_hdr_section)
|
if (eh_frame_hdr_section)
|
||||||
++phnum;
|
++phnum;
|
||||||
if (d->roinf)
|
|
||||||
++phnum;
|
|
||||||
{
|
|
||||||
int has_tls = 0;
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
s = s1->sections[i];
|
|
||||||
if (s->sh_flags & SHF_TLS) {
|
|
||||||
has_tls = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (has_tls)
|
|
||||||
++phnum;
|
|
||||||
}
|
|
||||||
d->phnum = phnum;
|
d->phnum = phnum;
|
||||||
d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
|
d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
|
||||||
|
|
||||||
@ -2415,7 +2419,7 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((f & 1<<8) && n) {
|
if ((f & SHFX_NEWPH) && n) {
|
||||||
/* different rwx section flags */
|
/* different rwx section flags */
|
||||||
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
|
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
|
||||||
/* if in the middle of a page, w e duplicate the page in
|
/* 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)
|
|||||||
s->sh_offset = file_offset;
|
s->sh_offset = file_offset;
|
||||||
s->sh_addr = addr;
|
s->sh_addr = addr;
|
||||||
|
|
||||||
if (f & 1<<8) {
|
addr += s->sh_size;
|
||||||
|
if (s->sh_type != SHT_NOBITS)
|
||||||
|
file_offset += s->sh_size;
|
||||||
|
|
||||||
|
if (f & SHFX_NEWPH) {
|
||||||
/* set new program header */
|
/* set new program header */
|
||||||
ph = &d->phdr[phfill + n];
|
ph = &d->phdr[phfill + n];
|
||||||
ph->p_type = PT_LOAD;
|
fill_phdr(ph, PT_LOAD, s);
|
||||||
ph->p_align = s_align;
|
ph->p_align = s_align;
|
||||||
ph->p_flags = PF_R;
|
|
||||||
if (f & SHF_WRITE)
|
if (f & SHF_WRITE)
|
||||||
ph->p_flags |= PF_W;
|
ph->p_flags |= PF_W;
|
||||||
if (f & SHF_EXECINSTR)
|
if (f & SHF_EXECINSTR)
|
||||||
ph->p_flags |= PF_X;
|
ph->p_flags |= PF_X;
|
||||||
|
|
||||||
ph->p_offset = file_offset;
|
|
||||||
ph->p_vaddr = addr;
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
/* Make the first PT_LOAD segment include the program
|
/* Make the first PT_LOAD segment include the program
|
||||||
headers itself (and the ELF header as well), it'll
|
headers itself (and the ELF header as well), it'll
|
||||||
come out with same memory use but will make various
|
come out with same memory use but will make various
|
||||||
tools like binutils strip work better. */
|
tools like binutils strip work better. */
|
||||||
ph->p_offset = 0;
|
ph->p_offset = 0;
|
||||||
ph->p_vaddr = base;
|
ph->p_paddr = ph->p_vaddr = base;
|
||||||
}
|
}
|
||||||
ph->p_paddr = ph->p_vaddr;
|
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f & 1<<4) {
|
if (ph)
|
||||||
Section *roinf = &d->_roinf;
|
update_phdr(ph, 0, 0, addr, file_offset);
|
||||||
if (roinf->sh_size == 0) {
|
|
||||||
roinf->sh_offset = s->sh_offset;
|
if (f & SHFX_RELRO) {
|
||||||
roinf->sh_addr = s->sh_addr;
|
ph2 = update_phdr(&d->phdr[d->relro], PT_GNU_RELRO, s, addr, file_offset);
|
||||||
roinf->sh_addralign = 1;
|
ph2->p_align = 1;
|
||||||
}
|
|
||||||
roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addr += s->sh_size;
|
if (f & SHF_TLS) {
|
||||||
if (s->sh_type != SHT_NOBITS)
|
ph2 = update_phdr(&d->phdr[d->tls], PT_TLS, s, addr, file_offset);
|
||||||
file_offset += s->sh_size;
|
if (s->sh_addralign > ph2->p_align)
|
||||||
|
ph2->p_align = s->sh_addralign;
|
||||||
if (ph) {
|
|
||||||
ph->p_filesz = file_offset - ph->p_offset;
|
|
||||||
ph->p_memsz = addr - ph->p_vaddr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (d->tls) {
|
||||||
|
++ph;
|
||||||
|
/* for xxx-link.c:relocate() */
|
||||||
|
s1->tls_start = ph->p_vaddr;
|
||||||
|
s1->tls_end = s1->tls_start + ph->p_memsz + (-ph->p_memsz & (ph->p_align - 1));
|
||||||
|
}
|
||||||
|
if (d->relro)
|
||||||
|
++ph;
|
||||||
/* Fill other headers */
|
/* Fill other headers */
|
||||||
if (d->note)
|
if (d->note)
|
||||||
fill_phdr(++ph, PT_NOTE, d->note);
|
fill_phdr(++ph, PT_NOTE, d->note);
|
||||||
@ -2485,36 +2491,6 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
|||||||
fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W;
|
fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W;
|
||||||
if (eh_frame_hdr_section)
|
if (eh_frame_hdr_section)
|
||||||
fill_phdr(++ph, PT_GNU_EH_FRAME, eh_frame_hdr_section);
|
fill_phdr(++ph, PT_GNU_EH_FRAME, eh_frame_hdr_section);
|
||||||
if (d->roinf)
|
|
||||||
fill_phdr(++ph, PT_GNU_RELRO, d->roinf)->p_flags |= PF_W;
|
|
||||||
{
|
|
||||||
/* Create PT_TLS segment covering all TLS sections */
|
|
||||||
Section *tls_start_sec = NULL;
|
|
||||||
addr_t tls_start = 0, tls_end = 0;
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
s = s1->sections[i];
|
|
||||||
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
|
||||||
if (!tls_start_sec) {
|
|
||||||
tls_start_sec = s;
|
|
||||||
tls_start = s->sh_addr;
|
|
||||||
tls_end = s->sh_addr + s->sh_size;
|
|
||||||
} else {
|
|
||||||
if (s->sh_addr < tls_start)
|
|
||||||
tls_start = s->sh_addr;
|
|
||||||
if (s->sh_addr + s->sh_size > tls_end)
|
|
||||||
tls_end = s->sh_addr + s->sh_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tls_start_sec) {
|
|
||||||
ph = fill_phdr(++ph, PT_TLS, tls_start_sec);
|
|
||||||
ph->p_vaddr = tls_start;
|
|
||||||
ph->p_paddr = tls_start;
|
|
||||||
ph->p_filesz = tls_end - tls_start;
|
|
||||||
ph->p_memsz = ph->p_filesz;
|
|
||||||
ph->p_align = tls_start_sec->sh_addralign;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (d->interp)
|
if (d->interp)
|
||||||
fill_phdr(&d->phdr[1], PT_INTERP, d->interp);
|
fill_phdr(&d->phdr[1], PT_INTERP, d->interp);
|
||||||
if (phfill) {
|
if (phfill) {
|
||||||
@ -2823,7 +2799,7 @@ static void reorder_sections(TCCState *s1, int *sec_order)
|
|||||||
|
|
||||||
backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0]));
|
backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0]));
|
||||||
for (i = 0, nnew = 0, snew = NULL; i < s1->nb_sections; i++) {
|
for (i = 0, nnew = 0, snew = NULL; i < s1->nb_sections; i++) {
|
||||||
k = sec_order[i];
|
k = sec_order ? sec_order[i] : i;
|
||||||
s = s1->sections[k];
|
s = s1->sections[k];
|
||||||
if (!i || s->sh_name) {
|
if (!i || s->sh_name) {
|
||||||
backmap[k] = nnew;
|
backmap[k] = nnew;
|
||||||
@ -2986,7 +2962,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
interp = dynstr = dynamic = NULL;
|
interp = dynstr = dynamic = NULL;
|
||||||
sec_order = NULL;
|
sec_order = NULL;
|
||||||
dyninf.roinf = &dyninf._roinf;
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
#ifdef TCC_TARGET_ARM
|
||||||
create_arm_attribute_section (s1);
|
create_arm_attribute_section (s1);
|
||||||
@ -3008,10 +2983,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
dyninf.note = create_bsd_note_section (s1, ".note.tag", "FreeBSD");
|
dyninf.note = create_bsd_note_section (s1, ".note.tag", "FreeBSD");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TARGETOS_FreeBSD || TARGETOS_NetBSD
|
|
||||||
dyninf.roinf = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
|
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(s1);
|
||||||
resolve_common_syms(s1);
|
resolve_common_syms(s1);
|
||||||
|
|||||||
7
tccgen.c
7
tccgen.c
@ -8400,10 +8400,9 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY))
|
while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY))
|
||||||
tp = &tp->ref->type;
|
tp = &tp->ref->type;
|
||||||
if (type->t & VT_TLS) {
|
if (type->t & VT_TLS) {
|
||||||
if (has_init)
|
sec = find_section(tcc_state, has_init ? ".tdata" : ".tbss");
|
||||||
sec = tdata_section;
|
sec->sh_flags = SHF_ALLOC | SHF_WRITE | SHF_TLS;
|
||||||
else
|
sec->sh_type = has_init ? SHT_PROGBITS : SHT_NOBITS;
|
||||||
sec = tbss_section;
|
|
||||||
} else if (tp->t & VT_CONSTANT) {
|
} else if (tp->t & VT_CONSTANT) {
|
||||||
sec = rodata_section;
|
sec = rodata_section;
|
||||||
} else if (has_init) {
|
} else if (has_init) {
|
||||||
|
|||||||
@ -57,8 +57,8 @@ endif
|
|||||||
ifeq ($(CONFIG_OSX),yes)
|
ifeq ($(CONFIG_OSX),yes)
|
||||||
SKIP += 144_tls.test # TLS runtime not supported on Mach-O
|
SKIP += 144_tls.test # TLS runtime not supported on Mach-O
|
||||||
endif
|
endif
|
||||||
ifeq (,$(filter i386 x86_64 riscv64 arm64,$(ARCH)))
|
ifeq (-$(ARCH)-,-arm-)
|
||||||
SKIP += 144_tls.test # TLS only implemented on these architectures so far
|
SKIP += 144_tls.test # doesn't work currently
|
||||||
endif
|
endif
|
||||||
ifneq (-$(ARCH)-,-arm64-)
|
ifneq (-$(ARCH)-,-arm64-)
|
||||||
SKIP += 138_arm64_encoding.test
|
SKIP += 138_arm64_encoding.test
|
||||||
|
|||||||
@ -368,70 +368,29 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||||||
tcc_error_noabort("unexpected R_X86_64_TLSLD pattern");
|
tcc_error_noabort("unexpected R_X86_64_TLSLD pattern");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_X86_64_DTPOFF32:
|
case R_X86_64_DTPOFF32:
|
||||||
case R_X86_64_TPOFF32:
|
case R_X86_64_TPOFF32:
|
||||||
{
|
|
||||||
ElfW(Sym) *sym;
|
|
||||||
Section *sec;
|
|
||||||
int32_t x;
|
|
||||||
addr_t tls_start = 0, tls_end = 0, tls_align = 1;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
sec = s1->sections[sym->st_shndx];
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
Section *s = s1->sections[i];
|
|
||||||
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
|
||||||
if (!tls_start || s->sh_addr < tls_start)
|
|
||||||
tls_start = s->sh_addr;
|
|
||||||
if (s->sh_addr + s->sh_size > tls_end)
|
|
||||||
tls_end = s->sh_addr + s->sh_size;
|
|
||||||
if (s->sh_addralign > tls_align)
|
|
||||||
tls_align = s->sh_addralign;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tls_end > tls_start) {
|
|
||||||
addr_t tls_size = tls_end - tls_start;
|
|
||||||
addr_t aligned_size = (tls_size + tls_align - 1) & ~(tls_align - 1);
|
|
||||||
x = val - (tls_start + aligned_size);
|
|
||||||
} else {
|
|
||||||
x = val - sec->sh_addr - sec->data_offset;
|
|
||||||
}
|
|
||||||
add32le(ptr, x);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case R_X86_64_DTPOFF64:
|
case R_X86_64_DTPOFF64:
|
||||||
case R_X86_64_TPOFF64:
|
case R_X86_64_TPOFF64:
|
||||||
{
|
{
|
||||||
ElfW(Sym) *sym;
|
|
||||||
Section *sec;
|
|
||||||
int32_t x;
|
int32_t x;
|
||||||
addr_t tls_start = 0, tls_end = 0, tls_align = 1;
|
if (s1->tls_end) {
|
||||||
int i;
|
x = val - s1->tls_end;
|
||||||
|
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
sec = s1->sections[sym->st_shndx];
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
|
||||||
Section *s = s1->sections[i];
|
|
||||||
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
|
||||||
if (!tls_start || s->sh_addr < tls_start)
|
|
||||||
tls_start = s->sh_addr;
|
|
||||||
if (s->sh_addr + s->sh_size > tls_end)
|
|
||||||
tls_end = s->sh_addr + s->sh_size;
|
|
||||||
if (s->sh_addralign > tls_align)
|
|
||||||
tls_align = s->sh_addralign;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tls_end > tls_start) {
|
|
||||||
addr_t tls_size = tls_end - tls_start;
|
|
||||||
addr_t aligned_size = (tls_size + tls_align - 1) & ~(tls_align - 1);
|
|
||||||
x = val - (tls_start + aligned_size);
|
|
||||||
} else {
|
} else {
|
||||||
|
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
|
Section *sec = s1->sections[sym->st_shndx];
|
||||||
x = val - sec->sh_addr - sec->data_offset;
|
x = val - sec->sh_addr - sec->data_offset;
|
||||||
}
|
}
|
||||||
add64le(ptr, x);
|
switch (type) {
|
||||||
|
case R_X86_64_DTPOFF64:
|
||||||
|
case R_X86_64_TPOFF64:
|
||||||
|
add64le(ptr, x);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
add32le(ptr, x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R_X86_64_NONE:
|
case R_X86_64_NONE:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user