115 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// 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 18void __tsan_init(void **thr, void **proc, void (*cb)(long, void*));19void __tsan_fini();20void __tsan_map_shadow(void *addr, unsigned long size);21void __tsan_go_start(void *thr, void **chthr, void *pc);22void __tsan_go_end(void *thr);23void __tsan_proc_create(void **pproc);24void __tsan_proc_destroy(void *proc);25void __tsan_proc_wire(void *proc, void *thr);26void __tsan_proc_unwire(void *proc, void *thr);27void __tsan_read(void *thr, void *addr, void *pc);28void __tsan_write(void *thr, void *addr, void *pc);29void __tsan_func_enter(void *thr, void *pc);30void __tsan_func_exit(void *thr);31void __tsan_malloc(void *thr, void *pc, void *p, unsigned long sz);32void __tsan_free(void *p, unsigned long sz);33void __tsan_acquire(void *thr, void *addr);34void __tsan_release(void *thr, void *addr);35void __tsan_release_acquire(void *thr, void *addr);36void __tsan_release_merge(void *thr, void *addr);37 38void *current_proc;39 40void 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 layout51 * of Go programs looks like. To prevent running over existing mappings,52 * we pick an address slightly inside the Go heap region.53 */54void *go_heap = (void *)0xC011110000;55char *buf0;56 57void foobar() {}58void barfoo() {}59 60int main(void) {61 void *thr0 = 0;62 void *proc0 = 0;63 __tsan_init(&thr0, &proc0, symbolize_cb);64 current_proc = proc0;65 66#if defined(__riscv) && (__riscv_xlen == 64) && defined(__linux__)67 // Use correct go_heap for riscv64 sv39.68 if (65 - __builtin_clzl((unsigned long)__builtin_frame_address(0)) == 39) {69 go_heap = (void *)0x511100000;70 }71#endif72 73 // Allocate something resembling a heap in Go.74 buf0 = mmap(go_heap, 16384, PROT_READ | PROT_WRITE,75 MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0);76 if (buf0 == MAP_FAILED) {77 fprintf(stderr, "failed to allocate Go-like heap at %p; errno %d\n",78 go_heap, errno);79 return 1;80 }81 char *buf = (char*)((unsigned long)buf0 + (64<<10) - 1 & ~((64<<10) - 1));82 __tsan_map_shadow(buf, 4096);83 __tsan_malloc(thr0, (char*)&barfoo + 1, buf, 10);84 __tsan_free(buf, 10);85 __tsan_func_enter(thr0, (char*)&main + 1);86 __tsan_malloc(thr0, (char*)&barfoo + 1, buf, 10);87 __tsan_release(thr0, buf);88 __tsan_release_acquire(thr0, buf);89 __tsan_release_merge(thr0, buf);90 void *thr1 = 0;91 __tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);92 void *thr2 = 0;93 __tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);94 __tsan_func_exit(thr0);95 __tsan_func_enter(thr1, (char*)&foobar + 1);96 __tsan_func_enter(thr1, (char*)&foobar + 1);97 __tsan_write(thr1, buf, (char*)&barfoo + 1);98 __tsan_acquire(thr1, buf);99 __tsan_func_exit(thr1);100 __tsan_func_exit(thr1);101 __tsan_go_end(thr1);102 void *proc1 = 0;103 __tsan_proc_create(&proc1);104 current_proc = proc1;105 __tsan_func_enter(thr2, (char*)&foobar + 1);106 __tsan_read(thr2, buf, (char*)&barfoo + 1);107 __tsan_free(buf, 10);108 __tsan_func_exit(thr2);109 __tsan_go_end(thr2);110 __tsan_proc_destroy(proc1);111 current_proc = proc0;112 __tsan_fini();113 return 0;114}115