mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
feat(riscv64): add TLS Local Exec code generation and linker relocations
This commit is contained in:
parent
ea26b85ac0
commit
11f5c6e1f9
@ -179,6 +179,19 @@ static int load_symofs(int r, SValue *sv, int forstore, int *new_fc)
|
||||
if (sv->r & VT_SYM) {
|
||||
Sym label = {0};
|
||||
assert(v == VT_CONST);
|
||||
if (sv->sym->type.t & VT_TLS) {
|
||||
/* TLS Local Exec model: lui + addi + add tp */
|
||||
rr = is_ireg(r) ? ireg(r) : 5;
|
||||
greloca(cur_text_section, sv->sym, ind,
|
||||
R_RISCV_TPREL_HI20, sv->c.i);
|
||||
o(0x37 | (rr << 7)); // lui RR, 0 %tprel_hi(sym)
|
||||
greloca(cur_text_section, sv->sym, ind,
|
||||
R_RISCV_TPREL_LO12_I, 0);
|
||||
EI(0x13, 0, rr, rr, 0); // addi RR, RR, 0 %tprel_lo(sym)
|
||||
ER(0x33, 0, rr, rr, 4, 0); // add RR, RR, tp
|
||||
*new_fc = 0;
|
||||
return rr;
|
||||
}
|
||||
if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax
|
||||
greloca(cur_text_section, sv->sym, ind,
|
||||
R_RISCV_PCREL_HI20, sv->c.i);
|
||||
|
||||
@ -53,6 +53,8 @@ ST_FUNC int code_reloc (int reloc_type)
|
||||
case R_RISCV_64:
|
||||
case R_RISCV_SET_ULEB128:
|
||||
case R_RISCV_SUB_ULEB128:
|
||||
case R_RISCV_TPREL_HI20:
|
||||
case R_RISCV_TPREL_LO12_I:
|
||||
return 0;
|
||||
|
||||
case R_RISCV_CALL_PLT:
|
||||
@ -101,6 +103,10 @@ ST_FUNC int gotplt_entry_type (int reloc_type)
|
||||
|
||||
case R_RISCV_GOT_HI20:
|
||||
return ALWAYS_GOTPLT_ENTRY;
|
||||
|
||||
case R_RISCV_TPREL_HI20:
|
||||
case R_RISCV_TPREL_LO12_I:
|
||||
return NO_GOTPLT_ENTRY;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -399,6 +405,31 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||
RELATIVE relocations from object files. */
|
||||
return;
|
||||
|
||||
case R_RISCV_TPREL_HI20:
|
||||
case R_RISCV_TPREL_LO12_I: {
|
||||
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;
|
||||
}
|
||||
}
|
||||
int64_t tp_offset = val - tls_start;
|
||||
if (type == R_RISCV_TPREL_HI20) {
|
||||
off64 = (int64_t)(tp_offset + 0x800) >> 12;
|
||||
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
||||
tcc_error_noabort("R_RISCV_TPREL_HI20 relocation failed");
|
||||
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||
| ((off64 & 0xfffff) << 12));
|
||||
} else {
|
||||
write32le(ptr, (read32le(ptr) & 0xfffff)
|
||||
| (((tp_offset) & 0xfff) << 20));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
|
||||
type, (unsigned)addr, ptr, (unsigned)val);
|
||||
|
||||
@ -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,$(ARCH)))
|
||||
ifeq (,$(filter x86_64 riscv64,$(ARCH)))
|
||||
SKIP += 144_tls.test # TLS only implemented on x86_64 so far
|
||||
endif
|
||||
ifeq ($(CONFIG_backtrace),no)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user