mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
feat(i386): add TLS Local Exec code generation and linker relocations
This commit is contained in:
parent
841ce0da03
commit
8502540b4a
20
i386-gen.c
20
i386-gen.c
@ -313,6 +313,16 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
#endif
|
||||
|
||||
if (fr & VT_LVAL) {
|
||||
if ((fr & VT_SYM) && sv->sym->type.t & VT_TLS) {
|
||||
int dst_reg = REG_VALUE(r);
|
||||
o(0x65); /* gs segment prefix */
|
||||
o(0x8b); /* mov r/m, r */
|
||||
o(0x04 | (dst_reg << 3)); /* modrm: [sib] | destreg */
|
||||
o(0x25); /* sib: disp32 */
|
||||
greloca(cur_text_section, sv->sym, ind, R_386_TLS_LE, fc);
|
||||
gen_le32(0);
|
||||
return;
|
||||
}
|
||||
if (v == VT_LLOCAL) {
|
||||
v1.type.t = VT_INT;
|
||||
v1.r = VT_LOCAL | VT_LVAL;
|
||||
@ -429,6 +439,16 @@ ST_FUNC void store(int r, SValue *v)
|
||||
} else
|
||||
#endif
|
||||
|
||||
if ((fr & VT_SYM) && v->sym->type.t & VT_TLS) {
|
||||
o(0x65); /* gs segment prefix */
|
||||
o(opc);
|
||||
o(0x04 | (REG_VALUE(r) << 3)); /* modrm: [sib] | srcreg */
|
||||
o(0x25); /* sib: disp32 */
|
||||
greloca(cur_text_section, v->sym, ind, R_386_TLS_LE, fc);
|
||||
gen_le32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
|
||||
gen_modrm(opc, r, v->r, v->sym, fc);
|
||||
} else if (fr != r) {
|
||||
|
||||
33
i386-link.c
33
i386-link.c
@ -305,7 +305,6 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||
}
|
||||
return;
|
||||
case R_386_TLS_LDO_32:
|
||||
case R_386_TLS_LE:
|
||||
{
|
||||
ElfW(Sym) *sym;
|
||||
Section *sec;
|
||||
@ -317,6 +316,38 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||
add32le(ptr, x);
|
||||
}
|
||||
return;
|
||||
case R_386_TLS_LE:
|
||||
{
|
||||
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);
|
||||
}
|
||||
return;
|
||||
case R_386_NONE:
|
||||
return;
|
||||
default:
|
||||
|
||||
@ -19,7 +19,7 @@ ifeq (,$(filter i386 x86_64,$(ARCH)))
|
||||
SKIP += 85_asm-outside-function.test # x86 asm
|
||||
SKIP += 127_asm_goto.test # hardcodes x86 asm
|
||||
endif
|
||||
ifeq (,$(filter x86_64 riscv64 arm64 arm,$(ARCH)))
|
||||
ifeq (,$(filter x86_64 riscv64 arm64 arm i386,$(ARCH)))
|
||||
SKIP += 144_tls.test # TLS only implemented on these architectures so far
|
||||
endif
|
||||
ifeq ($(CONFIG_backtrace),no)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user