//go:build enable_antithesis_sdk && linux && amd64 && cgo package internal import ( "fmt" "unsafe" "os" ) // -------------------------------------------------------------------------------- // To build and run an executable with this package // // CC=clang CGO_ENABLED=1 go run ./main.go // -------------------------------------------------------------------------------- // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ // // The commented lines below, and the `import "C"` line which must directly follow // the commented lines are used by CGO. They are load-bearing, and should not be // changed without first understanding how CGO uses them. // // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ // #cgo LDFLAGS: -ldl // // #include // #include // #include // #include // // typedef void (*go_fuzz_json_data_fn)(const char *data, size_t size); // void // go_fuzz_json_data(void *f, const char *data, size_t size) { // ((go_fuzz_json_data_fn)f)(data, size); // } // // typedef void (*go_fuzz_flush_fn)(void); // void // go_fuzz_flush(void *f) { // ((go_fuzz_flush_fn)f)(); // } // // typedef uint64_t (*go_fuzz_get_random_fn)(void); // uint64_t // go_fuzz_get_random(void *f) { // return ((go_fuzz_get_random_fn)f)(); // } // // typedef bool (*go_notify_coverage_fn)(size_t); // int // go_notify_coverage(void *f, size_t edges) { // bool b = ((go_notify_coverage_fn)f)(edges); // return b ? 1 : 0; // } // // typedef uint64_t (*go_init_coverage_fn)(size_t num_edges, const char *symbols); // uint64_t // go_init_coverage(void *f, size_t num_edges, const char *symbols) { // return ((go_init_coverage_fn)f)(num_edges, symbols); // } // import "C" const ( defaultNativeLibraryPath = "/usr/lib/libvoidstar.so" ) type voidstarHandler struct { fuzzJsonData unsafe.Pointer fuzzFlush unsafe.Pointer fuzzGetRandom unsafe.Pointer initCoverage unsafe.Pointer notifyCoverage unsafe.Pointer } func (h *voidstarHandler) output(message string) { msg_len := len(message) if msg_len == 0 { return } cstrMessage := C.CString(message) defer C.free(unsafe.Pointer(cstrMessage)) C.go_fuzz_json_data(h.fuzzJsonData, cstrMessage, C.ulong(msg_len)) C.go_fuzz_flush(h.fuzzFlush) } func (h *voidstarHandler) random() uint64 { return uint64(C.go_fuzz_get_random(h.fuzzGetRandom)) } func (h *voidstarHandler) init_coverage(num_edge uint64, symbols string) uint64 { cstrSymbols := C.CString(symbols) defer C.free(unsafe.Pointer(cstrSymbols)) return uint64(C.go_init_coverage(h.initCoverage, C.ulong(num_edge), cstrSymbols)) } func (h *voidstarHandler) notify(edge uint64) bool { ival := int(C.go_notify_coverage(h.notifyCoverage, C.ulong(edge))) return ival == 1 } // Attempt to load libvoidstar and some symbols from `path` func openSharedLib(path string) (*voidstarHandler, error) { cstrPath := C.CString(path) defer C.free(unsafe.Pointer(cstrPath)) dlError := func(message string) error { return fmt.Errorf("%s: (%s)", message, C.GoString(C.dlerror())) } sharedLib := C.dlopen(cstrPath, C.int(C.RTLD_NOW)) if sharedLib == nil { return nil, dlError("Can not load the Antithesis native library") } loadFunc := func(name string) (symbol unsafe.Pointer, err error) { cstrName := C.CString(name) defer C.free(unsafe.Pointer(cstrName)) if symbol = C.dlsym(sharedLib, cstrName); symbol == nil { err = dlError(fmt.Sprintf("Can not access symbol %s", name)) } return } fuzzJsonData, err := loadFunc("fuzz_json_data") if err != nil { return nil, err } fuzzFlush, err := loadFunc("fuzz_flush") if err != nil { return nil, err } fuzzGetRandom, err := loadFunc("fuzz_get_random") if err != nil { return nil, err } notifyCoverage, err := loadFunc("notify_coverage") if err != nil { return nil, err } initCoverage, err := loadFunc("init_coverage_module") if err != nil { return nil, err } return &voidstarHandler{fuzzJsonData, fuzzFlush, fuzzGetRandom, initCoverage, notifyCoverage}, nil } // If we have a file at `defaultNativeLibraryPath`, we load the shared library // (and panic on any error encountered during load). func init_in_antithesis() libHandler { if _, err := os.Stat(defaultNativeLibraryPath); err == nil { handler, err := openSharedLib(defaultNativeLibraryPath) if err != nil { panic(err) } return handler } return nil }