h_segv.c revision 1.4
11.4Skamil/*	$NetBSD: h_segv.c,v 1.4 2018/05/22 04:32:56 kamil Exp $	*/
21.1Schristos
31.1Schristos/*-
41.1Schristos * Copyright (c) 2017 The NetBSD Foundation, Inc.
51.1Schristos * All rights reserved.
61.1Schristos *
71.1Schristos * This code is derived from software contributed to The NetBSD Foundation
81.1Schristos * by Christos Zoulas.
91.1Schristos *
101.1Schristos * Redistribution and use in source and binary forms, with or without
111.1Schristos * modification, are permitted provided that the following conditions
121.1Schristos * are met:
131.1Schristos * 1. Redistributions of source code must retain the above copyright
141.1Schristos *    notice, this list of conditions and the following disclaimer.
151.1Schristos * 2. Redistributions in binary form must reproduce the above copyright
161.1Schristos *    notice, this list of conditions and the following disclaimer in the
171.1Schristos *    documentation and/or other materials provided with the distribution.
181.1Schristos *
191.1Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201.1Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211.1Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221.1Schristos * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231.1Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241.1Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251.1Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261.1Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271.1Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281.1Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291.1Schristos * POSSIBILITY OF SUCH DAMAGE.
301.1Schristos */
311.1Schristos#include <sys/cdefs.h>
321.4Skamil__RCSID("$NetBSD: h_segv.c,v 1.4 2018/05/22 04:32:56 kamil Exp $");
331.1Schristos
341.4Skamil#include <sys/types.h>
351.4Skamil#include <sys/ptrace.h>
361.1Schristos#include <stdio.h>
371.1Schristos#include <string.h>
381.1Schristos#include <stdlib.h>
391.1Schristos#include <unistd.h>
401.1Schristos#include <signal.h>
411.1Schristos#include <err.h>
421.1Schristos
431.1Schristos// A faulting address
441.1Schristosstatic int *p = (int *) 0xfefefef0;
451.1Schristos
461.1Schristosstatic int flags;
471.1Schristos#define F_RECURSE 	1
481.1Schristos#define F_HANDLE	2
491.1Schristos#define F_MASK		4
501.3Skamil#define F_IGNORE	8
511.1Schristos
521.1Schristosstatic struct {
531.1Schristos	const char *n;
541.1Schristos	int v;
551.1Schristos} nv[] = {
561.1Schristos	{ "recurse",	F_RECURSE },
571.1Schristos	{ "handle",	F_HANDLE },
581.1Schristos	{ "mask",	F_MASK },
591.3Skamil	{ "ignore",	F_IGNORE }
601.1Schristos};
611.1Schristos
621.4Skamilstatic int sig;
631.4Skamilstatic struct {
641.4Skamil	const char *n;
651.4Skamil	int v;
661.4Skamil} sn[] = {
671.4Skamil	{ "segv",	SIGSEGV },
681.4Skamil	{ "trap",	SIGTRAP }
691.4Skamil};
701.4Skamil
711.1Schristosstatic void
721.1Schristosfoo(int s)
731.1Schristos{
741.1Schristos        char buf[64];
751.1Schristos        int i = snprintf(buf, sizeof(buf), "got %d\n", s);
761.1Schristos        write(2, buf, i);
771.4Skamil	if (flags & F_RECURSE) {
781.4Skamil		if (sig == SIGSEGV)
791.4Skamil			*p = 0;
801.4Skamil		else if (sig == SIGTRAP) {
811.4Skamil#ifdef PTRACE_BREAKPOINT_ASM
821.4Skamil			PTRACE_BREAKPOINT_ASM;
831.4Skamil#else
841.4Skamil			/* port me */
851.4Skamil#endif
861.4Skamil		}
871.4Skamil	}
881.1Schristos        exit(EXIT_SUCCESS);
891.1Schristos}
901.1Schristos
911.1Schristosstatic __dead void
921.1Schristosusage(void)
931.1Schristos{
941.4Skamil	const char *pname = getprogname();
951.4Skamil
961.4Skamil	fprintf(stderr, "Usage: %s recurse|mask|handle|ignore ...\n", pname);
971.1Schristos	exit(EXIT_FAILURE);
981.1Schristos}
991.1Schristos
1001.1Schristosint
1011.1Schristosmain(int argc, char *argv[])
1021.1Schristos{
1031.1Schristos	if (argc == 1)
1041.1Schristos	    usage();
1051.1Schristos
1061.1Schristos	for (int i = 1; i < argc; i++) {
1071.1Schristos		size_t j;
1081.4Skamil		for (j = 0; j < __arraycount(nv); j++) {
1091.1Schristos			if (strcmp(nv[j].n, argv[i]) == 0) {
1101.1Schristos				flags |= nv[j].v;
1111.1Schristos				break;
1121.1Schristos			}
1131.4Skamil			if (strcmp(sn[j].n, argv[i]) == 0) {
1141.4Skamil				sig = sn[j].v;
1151.4Skamil				break;
1161.4Skamil			}
1171.4Skamil		}
1181.1Schristos		if (j == __arraycount(nv))
1191.1Schristos			usage();
1201.1Schristos	}
1211.1Schristos
1221.4Skamil	if (flags == 0 || sig == 0)
1231.1Schristos		usage();
1241.1Schristos
1251.1Schristos	if (flags & F_HANDLE) {
1261.1Schristos		struct sigaction sa;
1271.1Schristos
1281.1Schristos		sa.sa_flags = SA_RESTART;
1291.1Schristos		sa.sa_handler = foo;
1301.1Schristos		sigemptyset(&sa.sa_mask);
1311.4Skamil		if (sigaction(sig, &sa, NULL) == -1)
1321.1Schristos			err(EXIT_FAILURE, "sigaction");
1331.1Schristos	}
1341.1Schristos
1351.1Schristos	if (flags & F_MASK) {
1361.1Schristos		sigset_t set;
1371.1Schristos
1381.1Schristos		sigemptyset(&set);
1391.4Skamil		sigaddset(&set, sig);
1401.1Schristos		if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
1411.1Schristos			err(EXIT_FAILURE, "sigprocmask");
1421.1Schristos	}
1431.1Schristos
1441.3Skamil	if (flags & F_IGNORE) {
1451.3Skamil		struct sigaction sa;
1461.3Skamil
1471.3Skamil		memset(&sa, 0, sizeof(sa));
1481.3Skamil		sa.sa_handler = SIG_IGN;
1491.3Skamil		sigemptyset(&sa.sa_mask);
1501.4Skamil		if (sigaction(sig, &sa, NULL) == -1)
1511.3Skamil			err(EXIT_FAILURE, "sigaction");
1521.3Skamil	}
1531.3Skamil
1541.4Skamil	if (sig == SIGSEGV)
1551.4Skamil	        *p = 1;
1561.4Skamil	else if (sig == SIGTRAP) {
1571.4Skamil#ifdef PTRACE_BREAKPOINT_ASM
1581.4Skamil		PTRACE_BREAKPOINT_ASM;
1591.4Skamil#else
1601.4Skamil		/* port me */
1611.4Skamil#endif
1621.4Skamil	}
1631.1Schristos	return EXIT_SUCCESS;
1641.1Schristos}
165