1 //===-- test.c ------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Sanity test for Go runtime. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include <sys/mman.h> 14 #include <errno.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 18 void __tsan_init(void **thr, void **proc, void (*cb)(long, void*)); 19 void __tsan_fini(); 20 void __tsan_map_shadow(void *addr, unsigned long size); 21 void __tsan_go_start(void *thr, void **chthr, void *pc); 22 void __tsan_go_end(void *thr); 23 void __tsan_proc_create(void **pproc); 24 void __tsan_proc_destroy(void *proc); 25 void __tsan_proc_wire(void *proc, void *thr); 26 void __tsan_proc_unwire(void *proc, void *thr); 27 void __tsan_read(void *thr, void *addr, void *pc); 28 void __tsan_write(void *thr, void *addr, void *pc); 29 void __tsan_func_enter(void *thr, void *pc); 30 void __tsan_func_exit(void *thr); 31 void __tsan_malloc(void *thr, void *pc, void *p, unsigned long sz); 32 void __tsan_free(void *p, unsigned long sz); 33 void __tsan_acquire(void *thr, void *addr); 34 void __tsan_release(void *thr, void *addr); 35 void __tsan_release_acquire(void *thr, void *addr); 36 void __tsan_release_merge(void *thr, void *addr); 37 38 void *current_proc; 39 40 void symbolize_cb(long cmd, void *ctx) { 41 switch (cmd) { 42 case 0: 43 if (current_proc == 0) 44 abort(); 45 *(void**)ctx = current_proc; 46 } 47 } 48 49 /* 50 * See lib/tsan/rtl/tsan_platform.h for details of what the memory layout 51 * of Go programs looks like. To prevent running over existing mappings, 52 * we pick an address slightly inside the Go heap region. 53 */ 54 void *go_heap = (void *)0xC011110000; 55 char *buf0; 56 57 void foobar() {} 58 void barfoo() {} 59 60 int main(void) { 61 void *thr0 = 0; 62 void *proc0 = 0; 63 __tsan_init(&thr0, &proc0, symbolize_cb); 64 current_proc = proc0; 65 66 // Allocate something resembling a heap in Go. 67 buf0 = mmap(go_heap, 16384, PROT_READ | PROT_WRITE, 68 MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0); 69 if (buf0 == MAP_FAILED) { 70 fprintf(stderr, "failed to allocate Go-like heap at %p; errno %d\n", 71 go_heap, errno); 72 return 1; 73 } 74 char *buf = (char*)((unsigned long)buf0 + (64<<10) - 1 & ~((64<<10) - 1)); 75 __tsan_map_shadow(buf, 4096); 76 __tsan_malloc(thr0, (char*)&barfoo + 1, buf, 10); 77 __tsan_free(buf, 10); 78 __tsan_func_enter(thr0, (char*)&main + 1); 79 __tsan_malloc(thr0, (char*)&barfoo + 1, buf, 10); 80 __tsan_release(thr0, buf); 81 __tsan_release_acquire(thr0, buf); 82 __tsan_release_merge(thr0, buf); 83 void *thr1 = 0; 84 __tsan_go_start(thr0, &thr1, (char*)&barfoo + 1); 85 void *thr2 = 0; 86 __tsan_go_start(thr0, &thr2, (char*)&barfoo + 1); 87 __tsan_func_exit(thr0); 88 __tsan_func_enter(thr1, (char*)&foobar + 1); 89 __tsan_func_enter(thr1, (char*)&foobar + 1); 90 __tsan_write(thr1, buf, (char*)&barfoo + 1); 91 __tsan_acquire(thr1, buf); 92 __tsan_func_exit(thr1); 93 __tsan_func_exit(thr1); 94 __tsan_go_end(thr1); 95 void *proc1 = 0; 96 __tsan_proc_create(&proc1); 97 current_proc = proc1; 98 __tsan_func_enter(thr2, (char*)&foobar + 1); 99 __tsan_read(thr2, buf, (char*)&barfoo + 1); 100 __tsan_free(buf, 10); 101 __tsan_func_exit(thr2); 102 __tsan_go_end(thr2); 103 __tsan_proc_destroy(proc1); 104 current_proc = proc0; 105 __tsan_fini(); 106 return 0; 107 } 108