History

feat(x86_64): add TLS Local Exec support with tests

Meng Zhuo committed 6 months ago

Commit ea26b851 parent 8443e255 files · +141 −6Browse files

Unified · Split

5 files
  1. tests/tests2/144_tls.c +50 −0
  2. tests/tests2/144_tls.expect +8 −0
  3. tests/tests2/Makefile +7 −0
  4. x86_64-gen.c +29 −1
  5. x86_64-link.c +47 −5
tests/tests2/144_tls.c+50−0
@@ -0,0 +1,50 @@
1#include <stdio.h>
2#include <pthread.h>
3
4__thread int tls_init = 42;
5__thread int tls_zero;
6
7static void *thread_func(void *arg)
8{
9 (void)arg;
10
11 printf("%d\n", tls_init);
12 if (tls_init != 42) return (void *)1;
13
14 printf("%d\n", tls_zero);
15 if (tls_zero != 0) return (void *)1;
16
17 tls_init = 100;
18 tls_zero = 200;
19
20 printf("%d\n", tls_init);
21 printf("%d\n", tls_zero);
22
23 return (void *)0;
24}
25
26int main()
27{
28 pthread_t t;
29 void *ret;
30 int errors = 0;
31
32 printf("%d\n", tls_init);
33 if (tls_init != 42) errors = 1;
34
35 printf("%d\n", tls_zero);
36 if (tls_zero != 0) errors = 1;
37
38 pthread_create(&t, NULL, thread_func, NULL);
39 pthread_join(t, &ret);
40
41 if (ret) errors = 1;
42
43 printf("%d\n", tls_init);
44 if (tls_init != 42) errors = 1;
45
46 printf("%d\n", tls_zero);
47 if (tls_zero != 0) errors = 1;
48
49 return errors;
50}
tests/tests2/144_tls.expect+8−0
@@ -0,0 +1,8 @@
142
20
342
40
5100
6200
742
80
tests/tests2/Makefile+7−0
@@ -19,6 +19,9 @@ ifeq (,$(filter i386 x86_64,$(ARCH))) · 18 unmodified lines
19 SKIP += 85_asm-outside-function.test # x86 asm19 SKIP += 85_asm-outside-function.test # x86 asm
20 SKIP += 127_asm_goto.test # hardcodes x86 asm20 SKIP += 127_asm_goto.test # hardcodes x86 asm
21endif21endif
22ifeq (,$(filter x86_64,$(ARCH)))
23 SKIP += 144_tls.test # TLS only implemented on x86_64 so far
24endif
22ifeq ($(CONFIG_backtrace),no)25ifeq ($(CONFIG_backtrace),no)
23 SKIP += 113_btdll.test26 SKIP += 113_btdll.test
24 CONFIG_bcheck = no27 CONFIG_bcheck = no
@@ -107,6 +110,10 @@ GEN-ALWAYS = · 82 unmodified lines
107# constructor/destructor110# constructor/destructor
108108_constructor.test: NORUN = true111108_constructor.test: NORUN = true
109 112
113# TLS needs executable and pthread, not -run
114144_tls.test: FLAGS += -pthread
115144_tls.test: NORUN = true
116
110112_backtrace.test: FLAGS += -dt -b117112_backtrace.test: FLAGS += -dt -b
111112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \118112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \
112 -e 's;[0-9A-Fa-fx]\{5,\};........;g' \119 -e 's;[0-9A-Fa-fx]\{5,\};........;g' \
x86_64-gen.c+29−1
@@ -368,7 +368,8 @@ void load(int r, SValue *sv) · 367 unmodified lines
368#ifndef TCC_TARGET_PE368#ifndef TCC_TARGET_PE
369 /* we use indirect access via got */369 /* we use indirect access via got */
370 if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) &&370 if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) &&
371 (fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)) {371 (fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)
372 && !(sv->sym->type.t & VT_TLS)) {
372 /* use the result register as a temporal register */373 /* use the result register as a temporal register */
373 int tr = r | TREG_MEM;374 int tr = r | TREG_MEM;
374 if (is_float(ft)) {375 if (is_float(ft)) {
@@ -385,6 +386,19 @@ void load(int r, SValue *sv) · 10 unmodified lines
385 v = fr & VT_VALMASK;386 v = fr & VT_VALMASK;
386 if (fr & VT_LVAL) {387 if (fr & VT_LVAL) {
387 int b, ll;388 int b, ll;
389 if ((fr & VT_SYM) && sv->sym->type.t & VT_TLS) {
390 int dst_reg = REG_VALUE(r);
391 int is64 = is64_type(ft);
392 o(0x64); /* fs segment prefix */
393 if (is64 || REX_BASE(r))
394 o(0x40 | (REX_BASE(r) << 0) | (is64 << 3)); /* rex.w/rex.r */
395 o(0x8b); /* mov r/m, r */
396 o(0x04 | (dst_reg << 3)); /* modrm: [sib] | destreg */
397 o(0x25); /* sib: disp32 */
398 greloca(cur_text_section, sv->sym, ind, R_X86_64_TPOFF32, fc);
399 gen_le32(0);
400 return;
401 }
388 if (v == VT_LLOCAL) {402 if (v == VT_LLOCAL) {
389 v1.type.t = VT_PTR;403 v1.type.t = VT_PTR;
390 v1.r = VT_LOCAL | VT_LVAL;404 v1.r = VT_LOCAL | VT_LVAL;
@@ -572,6 +586,20 @@ void store(int r, SValue *v) · 181 unmodified lines
572 ft &= ~(VT_VOLATILE | VT_CONSTANT);586 ft &= ~(VT_VOLATILE | VT_CONSTANT);
573 bt = ft & VT_BTYPE;587 bt = ft & VT_BTYPE;
574 588
589 if ((v->r & VT_SYM) && v->sym->type.t & VT_TLS) {
590 int src_reg = REG_VALUE(r);
591 int is64 = is64_type(bt);
592 o(0x64);
593 if (is64 || REX_BASE(r))
594 o(0x40 | (REX_BASE(r) << 0) | (is64 << 3));
595 o(0x89);
596 o(0x04 | (src_reg << 3));
597 o(0x25);
598 greloca(cur_text_section, v->sym, ind, R_X86_64_TPOFF32, fc);
599 gen_le32(0);
600 return;
601 }
602
575#ifndef TCC_TARGET_PE603#ifndef TCC_TARGET_PE
576 /* we need to access the variable via got */604 /* we need to access the variable via got */
577 if (fr == VT_CONST605 if (fr == VT_CONST
x86_64-link.c+47−5
@@ -13,7 +13,7 @@ · 12 unmodified lines
13#define R_NUM R_X86_64_NUM13#define R_NUM R_X86_64_NUM
14 14
15#define ELF_START_ADDR 0x40000015#define ELF_START_ADDR 0x400000
16#define ELF_PAGE_SIZE 0x20000016#define ELF_PAGE_SIZE 0x1000
17 17
18#define PCRELATIVE_DLLPLT 118#define PCRELATIVE_DLLPLT 1
19#define RELOCATE_DLLPLT 119#define RELOCATE_DLLPLT 1
@@ -96,13 +96,15 @@ ST_FUNC int gotplt_entry_type (int reloc_type) · 76 unmodified lines
96 case R_X86_64_TLSGD:96 case R_X86_64_TLSGD:
97 case R_X86_64_TLSLD:97 case R_X86_64_TLSLD:
98 case R_X86_64_DTPOFF32:98 case R_X86_64_DTPOFF32:
99 case R_X86_64_TPOFF32:
100 case R_X86_64_DTPOFF64:99 case R_X86_64_DTPOFF64:
101 case R_X86_64_TPOFF64:
102 case R_X86_64_REX_GOTPCRELX:100 case R_X86_64_REX_GOTPCRELX:
103 case R_X86_64_PLT32:101 case R_X86_64_PLT32:
104 case R_X86_64_PLTOFF64:102 case R_X86_64_PLTOFF64:
105 return ALWAYS_GOTPLT_ENTRY;103 return ALWAYS_GOTPLT_ENTRY;
104
105 case R_X86_64_TPOFF32:
106 case R_X86_64_TPOFF64:
107 return NO_GOTPLT_ENTRY;
106 }108 }
107 109
108 return -1;110 return -1;
@@ -372,10 +374,30 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 263 unmodified lines
372 ElfW(Sym) *sym;374 ElfW(Sym) *sym;
373 Section *sec;375 Section *sec;
374 int32_t x;376 int32_t x;
377 addr_t tls_start = 0, tls_end = 0, tls_align = 1;
378 int i;
375 379
376 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];380 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
377 sec = s1->sections[sym->st_shndx];381 sec = s1->sections[sym->st_shndx];
378 x = val - sec->sh_addr - sec->data_offset;382
383 for (i = 1; i < s1->nb_sections; i++) {
384 Section *s = s1->sections[i];
385 if (s->sh_flags & SHF_TLS && s->sh_size) {
386 if (!tls_start || s->sh_addr < tls_start)
387 tls_start = s->sh_addr;
388 if (s->sh_addr + s->sh_size > tls_end)
389 tls_end = s->sh_addr + s->sh_size;
390 if (s->sh_addralign > tls_align)
391 tls_align = s->sh_addralign;
392 }
393 }
394 if (tls_end > tls_start) {
395 addr_t tls_size = tls_end - tls_start;
396 addr_t aligned_size = (tls_size + tls_align - 1) & ~(tls_align - 1);
397 x = val - (tls_start + aligned_size);
398 } else {
399 x = val - sec->sh_addr - sec->data_offset;
400 }
379 add32le(ptr, x);401 add32le(ptr, x);
380 }402 }
381 break;403 break;
@@ -385,10 +407,30 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 3 unmodified lines
385 ElfW(Sym) *sym;407 ElfW(Sym) *sym;
386 Section *sec;408 Section *sec;
387 int32_t x;409 int32_t x;
410 addr_t tls_start = 0, tls_end = 0, tls_align = 1;
411 int i;
388 412
389 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];413 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
390 sec = s1->sections[sym->st_shndx];414 sec = s1->sections[sym->st_shndx];
391 x = val - sec->sh_addr - sec->data_offset;415
416 for (i = 1; i < s1->nb_sections; i++) {
417 Section *s = s1->sections[i];
418 if (s->sh_flags & SHF_TLS && s->sh_size) {
419 if (!tls_start || s->sh_addr < tls_start)
420 tls_start = s->sh_addr;
421 if (s->sh_addr + s->sh_size > tls_end)
422 tls_end = s->sh_addr + s->sh_size;
423 if (s->sh_addralign > tls_align)
424 tls_align = s->sh_addralign;
425 }
426 }
427 if (tls_end > tls_start) {
428 addr_t tls_size = tls_end - tls_start;
429 addr_t aligned_size = (tls_size + tls_align - 1) & ~(tls_align - 1);
430 x = val - (tls_start + aligned_size);
431 } else {
432 x = val - sec->sh_addr - sec->data_offset;
433 }
392 add64le(ptr, x);434 add64le(ptr, x);
393 }435 }
394 break;436 break;

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