18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 2018, Breno Leitao, IBM Corp.
48c2ecf20Sopenharmony_ci * Licensed under GPLv2.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Sigfuz(tm): A PowerPC TM-aware signal fuzzer.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * This is a new selftest that raises SIGUSR1 signals and handles it in a set
98c2ecf20Sopenharmony_ci * of different ways, trying to create different scenario for testing
108c2ecf20Sopenharmony_ci * purpose.
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * This test works raising a signal and calling sigreturn interleaved with
138c2ecf20Sopenharmony_ci * TM operations, as starting, suspending and terminating a transaction. The
148c2ecf20Sopenharmony_ci * test depends on random numbers, and, based on them, it sets different TM
158c2ecf20Sopenharmony_ci * states.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * Other than that, the test fills out the user context struct that is passed
188c2ecf20Sopenharmony_ci * to the sigreturn system call with random data, in order to make sure that
198c2ecf20Sopenharmony_ci * the signal handler syscall can handle different and invalid states
208c2ecf20Sopenharmony_ci * properly.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * This selftest has command line parameters to control what kind of tests the
238c2ecf20Sopenharmony_ci * user wants to run, as for example, if a transaction should be started prior
248c2ecf20Sopenharmony_ci * to signal being raised, or, after the signal being raised and before the
258c2ecf20Sopenharmony_ci * sigreturn. If no parameter is given, the default is enabling all options.
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * This test does not check if the user context is being read and set
288c2ecf20Sopenharmony_ci * properly by the kernel. Its purpose, at this time, is basically
298c2ecf20Sopenharmony_ci * guaranteeing that the kernel does not crash on invalid scenarios.
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#include <stdio.h>
338c2ecf20Sopenharmony_ci#include <limits.h>
348c2ecf20Sopenharmony_ci#include <sys/wait.h>
358c2ecf20Sopenharmony_ci#include <unistd.h>
368c2ecf20Sopenharmony_ci#include <stdlib.h>
378c2ecf20Sopenharmony_ci#include <signal.h>
388c2ecf20Sopenharmony_ci#include <string.h>
398c2ecf20Sopenharmony_ci#include <ucontext.h>
408c2ecf20Sopenharmony_ci#include <sys/mman.h>
418c2ecf20Sopenharmony_ci#include <pthread.h>
428c2ecf20Sopenharmony_ci#include "utils.h"
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/* Selftest defaults */
458c2ecf20Sopenharmony_ci#define COUNT_MAX	600		/* Number of interactions */
468c2ecf20Sopenharmony_ci#define THREADS		16		/* Number of threads */
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* Arguments options */
498c2ecf20Sopenharmony_ci#define ARG_MESS_WITH_TM_AT	0x1
508c2ecf20Sopenharmony_ci#define ARG_MESS_WITH_TM_BEFORE	0x2
518c2ecf20Sopenharmony_ci#define ARG_MESS_WITH_MSR_AT	0x4
528c2ecf20Sopenharmony_ci#define ARG_FOREVER		0x10
538c2ecf20Sopenharmony_ci#define ARG_COMPLETE		(ARG_MESS_WITH_TM_AT |		\
548c2ecf20Sopenharmony_ci				ARG_MESS_WITH_TM_BEFORE |	\
558c2ecf20Sopenharmony_ci				ARG_MESS_WITH_MSR_AT)
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic int args;
588c2ecf20Sopenharmony_cistatic int nthread = THREADS;
598c2ecf20Sopenharmony_cistatic int count_max = COUNT_MAX;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/* checkpoint context */
628c2ecf20Sopenharmony_cistatic ucontext_t *tmp_uc;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/* Return true with 1/x probability */
658c2ecf20Sopenharmony_cistatic int one_in_chance(int x)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	return rand() % x == 0;
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/* Change TM states */
718c2ecf20Sopenharmony_cistatic void mess_with_tm(void)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	/* Starts a transaction 33% of the time */
748c2ecf20Sopenharmony_ci	if (one_in_chance(3)) {
758c2ecf20Sopenharmony_ci		asm ("tbegin.	;"
768c2ecf20Sopenharmony_ci		     "beq 8	;");
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci		/* And suspended half of them */
798c2ecf20Sopenharmony_ci		if (one_in_chance(2))
808c2ecf20Sopenharmony_ci			asm("tsuspend.	;");
818c2ecf20Sopenharmony_ci	}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	/* Call 'tend' in 5% of the runs */
848c2ecf20Sopenharmony_ci	if (one_in_chance(20))
858c2ecf20Sopenharmony_ci		asm("tend.	;");
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/* Signal handler that will be invoked with raise() */
898c2ecf20Sopenharmony_cistatic void trap_signal_handler(int signo, siginfo_t *si, void *uc)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	ucontext_t *ucp = uc;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	ucp->uc_link = tmp_uc;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	/*
968c2ecf20Sopenharmony_ci	 * Set uc_link in three possible ways:
978c2ecf20Sopenharmony_ci	 *  - Setting a single 'int' in the whole chunk
988c2ecf20Sopenharmony_ci	 *  - Cloning ucp into uc_link
998c2ecf20Sopenharmony_ci	 *  - Allocating a new memory chunk
1008c2ecf20Sopenharmony_ci	 */
1018c2ecf20Sopenharmony_ci	if (one_in_chance(3)) {
1028c2ecf20Sopenharmony_ci		memset(ucp->uc_link, rand(), sizeof(ucontext_t));
1038c2ecf20Sopenharmony_ci	} else if (one_in_chance(2)) {
1048c2ecf20Sopenharmony_ci		memcpy(ucp->uc_link, uc, sizeof(ucontext_t));
1058c2ecf20Sopenharmony_ci	} else if (one_in_chance(2)) {
1068c2ecf20Sopenharmony_ci		if (tmp_uc) {
1078c2ecf20Sopenharmony_ci			free(tmp_uc);
1088c2ecf20Sopenharmony_ci			tmp_uc = NULL;
1098c2ecf20Sopenharmony_ci		}
1108c2ecf20Sopenharmony_ci		tmp_uc = malloc(sizeof(ucontext_t));
1118c2ecf20Sopenharmony_ci		ucp->uc_link = tmp_uc;
1128c2ecf20Sopenharmony_ci		/* Trying to cause a major page fault at Kernel level */
1138c2ecf20Sopenharmony_ci		madvise(ucp->uc_link, sizeof(ucontext_t), MADV_DONTNEED);
1148c2ecf20Sopenharmony_ci	}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	if (args & ARG_MESS_WITH_MSR_AT) {
1178c2ecf20Sopenharmony_ci		/* Changing the checkpointed registers */
1188c2ecf20Sopenharmony_ci		if (one_in_chance(4)) {
1198c2ecf20Sopenharmony_ci			ucp->uc_link->uc_mcontext.gp_regs[PT_MSR] |= MSR_TS_S;
1208c2ecf20Sopenharmony_ci		} else {
1218c2ecf20Sopenharmony_ci			if (one_in_chance(2)) {
1228c2ecf20Sopenharmony_ci				ucp->uc_link->uc_mcontext.gp_regs[PT_MSR] |=
1238c2ecf20Sopenharmony_ci						 MSR_TS_T;
1248c2ecf20Sopenharmony_ci			} else if (one_in_chance(2)) {
1258c2ecf20Sopenharmony_ci				ucp->uc_link->uc_mcontext.gp_regs[PT_MSR] |=
1268c2ecf20Sopenharmony_ci						MSR_TS_T | MSR_TS_S;
1278c2ecf20Sopenharmony_ci			}
1288c2ecf20Sopenharmony_ci		}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci		/* Checking the current register context */
1318c2ecf20Sopenharmony_ci		if (one_in_chance(2)) {
1328c2ecf20Sopenharmony_ci			ucp->uc_mcontext.gp_regs[PT_MSR] |= MSR_TS_S;
1338c2ecf20Sopenharmony_ci		} else if (one_in_chance(2)) {
1348c2ecf20Sopenharmony_ci			if (one_in_chance(2))
1358c2ecf20Sopenharmony_ci				ucp->uc_mcontext.gp_regs[PT_MSR] |=
1368c2ecf20Sopenharmony_ci					MSR_TS_T;
1378c2ecf20Sopenharmony_ci			else if (one_in_chance(2))
1388c2ecf20Sopenharmony_ci				ucp->uc_mcontext.gp_regs[PT_MSR] |=
1398c2ecf20Sopenharmony_ci					MSR_TS_T | MSR_TS_S;
1408c2ecf20Sopenharmony_ci		}
1418c2ecf20Sopenharmony_ci	}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	if (one_in_chance(20)) {
1448c2ecf20Sopenharmony_ci		/* Nested transaction start */
1458c2ecf20Sopenharmony_ci		if (one_in_chance(5))
1468c2ecf20Sopenharmony_ci			mess_with_tm();
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci		/* Return without changing any other context info */
1498c2ecf20Sopenharmony_ci		return;
1508c2ecf20Sopenharmony_ci	}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	if (one_in_chance(10))
1538c2ecf20Sopenharmony_ci		ucp->uc_mcontext.gp_regs[PT_MSR] = random();
1548c2ecf20Sopenharmony_ci	if (one_in_chance(10))
1558c2ecf20Sopenharmony_ci		ucp->uc_mcontext.gp_regs[PT_NIP] = random();
1568c2ecf20Sopenharmony_ci	if (one_in_chance(10))
1578c2ecf20Sopenharmony_ci		ucp->uc_link->uc_mcontext.gp_regs[PT_MSR] = random();
1588c2ecf20Sopenharmony_ci	if (one_in_chance(10))
1598c2ecf20Sopenharmony_ci		ucp->uc_link->uc_mcontext.gp_regs[PT_NIP] = random();
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_TRAP] = random();
1628c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_DSISR] = random();
1638c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_DAR] = random();
1648c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_ORIG_R3] = random();
1658c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_XER] = random();
1668c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_RESULT] = random();
1678c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_SOFTE] = random();
1688c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_DSCR] = random();
1698c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_CTR] = random();
1708c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_LNK] = random();
1718c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_CCR] = random();
1728c2ecf20Sopenharmony_ci	ucp->uc_mcontext.gp_regs[PT_REGS_COUNT] = random();
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_TRAP] = random();
1758c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_DSISR] = random();
1768c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_DAR] = random();
1778c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_ORIG_R3] = random();
1788c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_XER] = random();
1798c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_RESULT] = random();
1808c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_SOFTE] = random();
1818c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_DSCR] = random();
1828c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_CTR] = random();
1838c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_LNK] = random();
1848c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_CCR] = random();
1858c2ecf20Sopenharmony_ci	ucp->uc_link->uc_mcontext.gp_regs[PT_REGS_COUNT] = random();
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	if (args & ARG_MESS_WITH_TM_BEFORE) {
1888c2ecf20Sopenharmony_ci		if (one_in_chance(2))
1898c2ecf20Sopenharmony_ci			mess_with_tm();
1908c2ecf20Sopenharmony_ci	}
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic void seg_signal_handler(int signo, siginfo_t *si, void *uc)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	/* Clear exit for process that segfaults */
1968c2ecf20Sopenharmony_ci	exit(0);
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic void *sigfuz_test(void *thrid)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	struct sigaction trap_sa, seg_sa;
2028c2ecf20Sopenharmony_ci	int ret, i = 0;
2038c2ecf20Sopenharmony_ci	pid_t t;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	tmp_uc = malloc(sizeof(ucontext_t));
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	/* Main signal handler */
2088c2ecf20Sopenharmony_ci	trap_sa.sa_flags = SA_SIGINFO;
2098c2ecf20Sopenharmony_ci	trap_sa.sa_sigaction = trap_signal_handler;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	/* SIGSEGV signal handler */
2128c2ecf20Sopenharmony_ci	seg_sa.sa_flags = SA_SIGINFO;
2138c2ecf20Sopenharmony_ci	seg_sa.sa_sigaction = seg_signal_handler;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	/* The signal handler will enable MSR_TS */
2168c2ecf20Sopenharmony_ci	sigaction(SIGUSR1, &trap_sa, NULL);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	/* If it does not crash, it will segfault, avoid it to retest */
2198c2ecf20Sopenharmony_ci	sigaction(SIGSEGV, &seg_sa, NULL);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	while (i < count_max) {
2228c2ecf20Sopenharmony_ci		t = fork();
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci		if (t == 0) {
2258c2ecf20Sopenharmony_ci			/* Once seed per process */
2268c2ecf20Sopenharmony_ci			srand(time(NULL) + getpid());
2278c2ecf20Sopenharmony_ci			if (args & ARG_MESS_WITH_TM_AT) {
2288c2ecf20Sopenharmony_ci				if (one_in_chance(2))
2298c2ecf20Sopenharmony_ci					mess_with_tm();
2308c2ecf20Sopenharmony_ci			}
2318c2ecf20Sopenharmony_ci			raise(SIGUSR1);
2328c2ecf20Sopenharmony_ci			exit(0);
2338c2ecf20Sopenharmony_ci		} else {
2348c2ecf20Sopenharmony_ci			waitpid(t, &ret, 0);
2358c2ecf20Sopenharmony_ci		}
2368c2ecf20Sopenharmony_ci		if (!(args & ARG_FOREVER))
2378c2ecf20Sopenharmony_ci			i++;
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	/* If not freed already, free now */
2418c2ecf20Sopenharmony_ci	if (tmp_uc) {
2428c2ecf20Sopenharmony_ci		free(tmp_uc);
2438c2ecf20Sopenharmony_ci		tmp_uc = NULL;
2448c2ecf20Sopenharmony_ci	}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	return NULL;
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic int signal_fuzzer(void)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	int t, rc;
2528c2ecf20Sopenharmony_ci	pthread_t *threads;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	threads = malloc(nthread * sizeof(pthread_t));
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	for (t = 0; t < nthread; t++) {
2578c2ecf20Sopenharmony_ci		rc = pthread_create(&threads[t], NULL, sigfuz_test,
2588c2ecf20Sopenharmony_ci				    (void *)&t);
2598c2ecf20Sopenharmony_ci		if (rc)
2608c2ecf20Sopenharmony_ci			perror("Thread creation error\n");
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	for (t = 0; t < nthread; t++) {
2648c2ecf20Sopenharmony_ci		rc = pthread_join(threads[t], NULL);
2658c2ecf20Sopenharmony_ci		if (rc)
2668c2ecf20Sopenharmony_ci			perror("Thread join error\n");
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	free(threads);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	return EXIT_SUCCESS;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cistatic void show_help(char *name)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	printf("%s: Sigfuzzer for powerpc\n", name);
2778c2ecf20Sopenharmony_ci	printf("Usage:\n");
2788c2ecf20Sopenharmony_ci	printf("\t-b\t Mess with TM before raising a SIGUSR1 signal\n");
2798c2ecf20Sopenharmony_ci	printf("\t-a\t Mess with TM after raising a SIGUSR1 signal\n");
2808c2ecf20Sopenharmony_ci	printf("\t-m\t Mess with MSR[TS] bits at mcontext\n");
2818c2ecf20Sopenharmony_ci	printf("\t-x\t Mess with everything above\n");
2828c2ecf20Sopenharmony_ci	printf("\t-f\t Run forever (Press ^C to Quit)\n");
2838c2ecf20Sopenharmony_ci	printf("\t-i\t Amount of interactions.	(Default = %d)\n", COUNT_MAX);
2848c2ecf20Sopenharmony_ci	printf("\t-t\t Amount of threads.	(Default = %d)\n", THREADS);
2858c2ecf20Sopenharmony_ci	exit(-1);
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ciint main(int argc, char **argv)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	int opt;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	while ((opt = getopt(argc, argv, "bamxt:fi:h")) != -1) {
2938c2ecf20Sopenharmony_ci		if (opt == 'b') {
2948c2ecf20Sopenharmony_ci			printf("Mess with TM before signal\n");
2958c2ecf20Sopenharmony_ci			args |= ARG_MESS_WITH_TM_BEFORE;
2968c2ecf20Sopenharmony_ci		} else if (opt == 'a') {
2978c2ecf20Sopenharmony_ci			printf("Mess with TM at signal handler\n");
2988c2ecf20Sopenharmony_ci			args |= ARG_MESS_WITH_TM_AT;
2998c2ecf20Sopenharmony_ci		} else if (opt == 'm') {
3008c2ecf20Sopenharmony_ci			printf("Mess with MSR[TS] bits in mcontext\n");
3018c2ecf20Sopenharmony_ci			args |= ARG_MESS_WITH_MSR_AT;
3028c2ecf20Sopenharmony_ci		} else if (opt == 'x') {
3038c2ecf20Sopenharmony_ci			printf("Running with all options enabled\n");
3048c2ecf20Sopenharmony_ci			args |= ARG_COMPLETE;
3058c2ecf20Sopenharmony_ci		} else if (opt == 't') {
3068c2ecf20Sopenharmony_ci			nthread = atoi(optarg);
3078c2ecf20Sopenharmony_ci			printf("Threads = %d\n", nthread);
3088c2ecf20Sopenharmony_ci		} else if (opt == 'f') {
3098c2ecf20Sopenharmony_ci			args |= ARG_FOREVER;
3108c2ecf20Sopenharmony_ci			printf("Press ^C to stop\n");
3118c2ecf20Sopenharmony_ci			test_harness_set_timeout(-1);
3128c2ecf20Sopenharmony_ci		} else if (opt == 'i') {
3138c2ecf20Sopenharmony_ci			count_max = atoi(optarg);
3148c2ecf20Sopenharmony_ci			printf("Running for %d interactions\n", count_max);
3158c2ecf20Sopenharmony_ci		} else if (opt == 'h') {
3168c2ecf20Sopenharmony_ci			show_help(argv[0]);
3178c2ecf20Sopenharmony_ci		}
3188c2ecf20Sopenharmony_ci	}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	/* Default test suite */
3218c2ecf20Sopenharmony_ci	if (!args)
3228c2ecf20Sopenharmony_ci		args = ARG_COMPLETE;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	test_harness(signal_fuzzer, "signal_fuzzer");
3258c2ecf20Sopenharmony_ci}
326