History

feat(arm64): add TLS Local Exec code generation and linker relocations

Meng Zhuo committed 6 months ago

Commit 8abaf101 parent 11f5c6e3 files · +75 −1Browse files

Unified · Split

3 files
  1. arm64-gen.c +49 −0
  2. arm64-link.c +25 −0
  3. tests/tests2/Makefile +1 −1
arm64-gen.c+49−0
@@ -552,6 +552,23 @@ ST_FUNC void load(int r, SValue *sv) · 551 unmodified lines
552552 }
553553
554554 if (svr == (VT_CONST | VT_LVAL | VT_SYM)) {
555+ if (sv->sym->type.t & VT_TLS) {
556+ o(0xd53bd05e); /* mrs x30, tpidr_el0 */
557+ greloca(cur_text_section, sv->sym, ind,
558+ R_AARCH64_TLSLE_ADD_TPREL_HI12, 0);
559+ o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) |
560+ ARM64_RN(30) | ARM64_RD(30)); /* add x30, x30, #0, lsl #12 */
561+ greloca(cur_text_section, sv->sym, ind,
562+ R_AARCH64_TLSLE_ADD_TPREL_LO12, 0);
563+ o(ARM64_ADD_IMM | ARM64_SF(1) |
564+ ARM64_RN(30) | ARM64_RD(30)); /* add x30, x30, #0 */
565+ if (IS_FREG(r))
566+ arm64_ldrv(arm64_type_size(svtt), fltr(r), 30, svcoff);
567+ else
568+ arm64_ldrx(!(svtt&VT_UNSIGNED), arm64_type_size(svtt),
569+ intr(r), 30, svcoff);
570+ return;
571+ }
555572 arm64_sym(30, sv->sym, // use x30 for address
556573 arm64_check_offset(0, arm64_type_size(svtt), svcoff));
557574 if (IS_FREG(r))
@@ -645,6 +662,22 @@ ST_FUNC void store(int r, SValue *sv) · 87 unmodified lines
645662 if (svr == (VT_CONST | VT_LVAL)) {
646663 uint64_t i = sv->c.i;
647664
665+ if (sv->sym && (sv->sym->type.t & VT_TLS)) {
666+ o(0xd53bd05e);
667+ greloca(cur_text_section, sv->sym, ind,
668+ R_AARCH64_TLSLE_ADD_TPREL_HI12, 0);
669+ o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) |
670+ ARM64_RN(30) | ARM64_RD(30));
671+ greloca(cur_text_section, sv->sym, ind,
672+ R_AARCH64_TLSLE_ADD_TPREL_LO12, 0);
673+ o(ARM64_ADD_IMM | ARM64_SF(1) |
674+ ARM64_RN(30) | ARM64_RD(30));
675+ if (IS_FREG(r))
676+ arm64_strv(arm64_type_size(svtt), fltr(r), 30, i);
677+ else
678+ arm64_strx(arm64_type_size(svtt), intr(r), 30, i);
679+ return;
680+ }
648681 if (sv->sym)
649682 arm64_sym(30, sv->sym, // use x30 for address
650683 arm64_check_offset(0, arm64_type_size(svtt), i));
@@ -668,6 +701,22 @@ ST_FUNC void store(int r, SValue *sv) · 17 unmodified lines
668701 }
669702
670703 if (svr == (VT_CONST | VT_LVAL | VT_SYM)) {
704+ if (sv->sym->type.t & VT_TLS) {
705+ o(0xd53bd05e); /* mrs x30, tpidr_el0 */
706+ greloca(cur_text_section, sv->sym, ind,
707+ R_AARCH64_TLSLE_ADD_TPREL_HI12, 0);
708+ o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) |
709+ ARM64_RN(30) | ARM64_RD(30)); /* add x30, x30, #0, lsl #12 */
710+ greloca(cur_text_section, sv->sym, ind,
711+ R_AARCH64_TLSLE_ADD_TPREL_LO12, 0);
712+ o(ARM64_ADD_IMM | ARM64_SF(1) |
713+ ARM64_RN(30) | ARM64_RD(30)); /* add x30, x30, #0 */
714+ if (IS_FREG(r))
715+ arm64_strv(arm64_type_size(svtt), fltr(r), 30, svcoff);
716+ else
717+ arm64_strx(arm64_type_size(svtt), intr(r), 30, svcoff);
718+ return;
719+ }
671720 arm64_sym(30, sv->sym, // use x30 for address
672721 arm64_check_offset(0, arm64_type_size(svtt), svcoff));
673722 if (IS_FREG(r))
arm64-link.c+25−0
@@ -43,6 +43,8 @@ ST_FUNC int code_reloc (int reloc_type) · 42 unmodified lines
4343 case R_AARCH64_LDST32_ABS_LO12_NC:
4444 case R_AARCH64_LDST16_ABS_LO12_NC:
4545 case R_AARCH64_LDST8_ABS_LO12_NC:
46+ case R_AARCH64_TLSLE_ADD_TPREL_HI12:
47+ case R_AARCH64_TLSLE_ADD_TPREL_LO12:
4648 case R_AARCH64_GLOB_DAT:
4749 case R_AARCH64_COPY:
4850 return 0;
@@ -80,6 +82,8 @@ ST_FUNC int gotplt_entry_type (int reloc_type) · 31 unmodified lines
8082 case R_AARCH64_COPY:
8183 case R_AARCH64_CONDBR19:
8284 case R_AARCH64_TSTBR14:
85+ case R_AARCH64_TLSLE_ADD_TPREL_HI12:
86+ case R_AARCH64_TLSLE_ADD_TPREL_LO12:
8387 return NO_GOTPLT_ENTRY;
8488
8589 case R_AARCH64_ABS32:
@@ -365,6 +369,27 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 279 unmodified lines
365369 #endif
366370 write64le(ptr, val - rel->r_addend);
367371 return;
372+ case R_AARCH64_TLSLE_ADD_TPREL_HI12:
373+ case R_AARCH64_TLSLE_ADD_TPREL_LO12: {
374+ addr_t tls_start = 0;
375+ int i;
376+ for (i = 1; i < s1->nb_sections; i++) {
377+ Section *s = s1->sections[i];
378+ if (s->sh_flags & SHF_TLS && s->sh_size) {
379+ if (!tls_start || s->sh_addr < tls_start)
380+ tls_start = s->sh_addr;
381+ }
382+ }
383+ /* glibc arm64: tp points to tcbhead_t (DTV), TLS data starts after it */
384+ int64_t tp_offset = val - tls_start + 16;
385+ int64_t imm;
386+ if (type == R_AARCH64_TLSLE_ADD_TPREL_HI12)
387+ imm = (tp_offset >> 12) & 0xfff;
388+ else
389+ imm = tp_offset & 0xfff;
390+ write32le(ptr, ((read32le(ptr) & 0xffc003ff) | (imm << 10)));
391+ return;
392+ }
368393 case R_AARCH64_RELATIVE:
369394 #ifdef TCC_TARGET_PE
370395 add32le(ptr, val - s1->pe_imagebase);
tests/tests2/Makefile+1−1
@@ -19,7 +19,7 @@ ifeq (,$(filter i386 x86_64,$(ARCH))) · 18 unmodified lines
1919 SKIP += 85_asm-outside-function.test # x86 asm
2020 SKIP += 127_asm_goto.test # hardcodes x86 asm
2121 endif
22−ifeq (,$(filter x86_64 riscv64,$(ARCH)))
22+ifeq (,$(filter x86_64 riscv64 arm64,$(ARCH)))
2323 SKIP += 144_tls.test # TLS only implemented on x86_64 so far
2424 endif
2525 ifeq ($(CONFIG_backtrace),no)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t