mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
feat(arm): add TLS Local Exec code generation and linker relocations
This commit is contained in:
parent
8abaf10ab5
commit
841ce0da03
24
arm-gen.c
24
arm-gen.c
@ -572,7 +572,7 @@ static void load_value(SValue *sv, int r)
|
||||
void load(int r, SValue *sv)
|
||||
{
|
||||
int v, ft, fc, fr, sign;
|
||||
uint32_t op;
|
||||
uint32_t op, base;
|
||||
SValue v1;
|
||||
|
||||
fr = sv->r;
|
||||
@ -588,7 +588,15 @@ void load(int r, SValue *sv)
|
||||
|
||||
v = fr & VT_VALMASK;
|
||||
if (fr & VT_LVAL) {
|
||||
uint32_t base = 0xB; // fp
|
||||
if ((fr & VT_SYM) && sv->sym->type.t & VT_TLS) {
|
||||
uint32_t op;
|
||||
o(0xee1d0fe0); /* mrc p15, 0, lr, c13, c0, 3 */
|
||||
op = 0xe510e000; /* ldr r, [lr, #0] */
|
||||
greloca(cur_text_section, sv->sym, ind, R_ARM_TLS_LE32, 0);
|
||||
o(op | (intr(r) << 12));
|
||||
return;
|
||||
}
|
||||
base = 0xB; // fp
|
||||
if(v == VT_LLOCAL) {
|
||||
v1.type.t = VT_PTR;
|
||||
v1.r = VT_LOCAL | VT_LVAL;
|
||||
@ -703,7 +711,7 @@ void store(int r, SValue *sv)
|
||||
{
|
||||
SValue v1;
|
||||
int v, ft, fc, fr, sign;
|
||||
uint32_t op;
|
||||
uint32_t op, base;
|
||||
|
||||
fr = sv->r;
|
||||
ft = sv->type.t;
|
||||
@ -718,7 +726,15 @@ void store(int r, SValue *sv)
|
||||
|
||||
v = fr & VT_VALMASK;
|
||||
if (fr & VT_LVAL || fr == VT_LOCAL) {
|
||||
uint32_t base = 0xb; /* fp */
|
||||
if ((fr & VT_SYM) && sv->sym->type.t & VT_TLS) {
|
||||
uint32_t op;
|
||||
o(0xee1d0fe0); /* mrc p15, 0, lr, c13, c0, 3 */
|
||||
op = 0xe500e000; /* str r, [lr, #0] */
|
||||
greloca(cur_text_section, sv->sym, ind, R_ARM_TLS_LE32, 0);
|
||||
o(op | (intr(r) << 12));
|
||||
return;
|
||||
}
|
||||
base = 0xb; /* fp */
|
||||
if(v < VT_CONST) {
|
||||
base=intr(v);
|
||||
v=VT_LOCAL;
|
||||
|
||||
32
arm-link.c
32
arm-link.c
@ -44,6 +44,7 @@ ST_FUNC int code_reloc (int reloc_type)
|
||||
case R_ARM_TARGET1:
|
||||
case R_ARM_MOVT_PREL:
|
||||
case R_ARM_MOVW_PREL_NC:
|
||||
case R_ARM_TLS_LE32:
|
||||
return 0;
|
||||
|
||||
case R_ARM_PC24:
|
||||
@ -70,6 +71,7 @@ ST_FUNC int gotplt_entry_type (int reloc_type)
|
||||
case R_ARM_COPY:
|
||||
case R_ARM_GLOB_DAT:
|
||||
case R_ARM_JUMP_SLOT:
|
||||
case R_ARM_TLS_LE32:
|
||||
return NO_GOTPLT_ENTRY;
|
||||
|
||||
case R_ARM_PC24:
|
||||
@ -430,6 +432,36 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||
#endif
|
||||
/* do nothing */
|
||||
return;
|
||||
case R_ARM_TLS_LE32:
|
||||
{
|
||||
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) {
|
||||
x = val - tls_start + 8;
|
||||
} else {
|
||||
x = val - sec->sh_addr - sec->data_offset + 8;
|
||||
}
|
||||
add32le(ptr, x);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
|
||||
type, (unsigned)addr, ptr, (unsigned)val);
|
||||
|
||||
@ -19,8 +19,8 @@ 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,$(ARCH)))
|
||||
SKIP += 144_tls.test # TLS only implemented on x86_64 so far
|
||||
ifeq (,$(filter x86_64 riscv64 arm64 arm,$(ARCH)))
|
||||
SKIP += 144_tls.test # TLS only implemented on these architectures so far
|
||||
endif
|
||||
ifeq ($(CONFIG_backtrace),no)
|
||||
SKIP += 113_btdll.test
|
||||
|
||||
Loading…
Reference in New Issue
Block a user