h_segv.c revision 1.9
11.9Sriastrad/* $NetBSD: h_segv.c,v 1.9 2018/11/11 01:26:08 riastradh 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.9Sriastrad__RCSID("$NetBSD: h_segv.c,v 1.9 2018/11/11 01:26:08 riastradh Exp $"); 331.1Schristos 341.4Skamil#include <sys/types.h> 351.5Skamil#include <sys/mman.h> 361.4Skamil#include <sys/ptrace.h> 371.8Sriastrad 381.8Sriastrad#include <err.h> 391.9Sriastrad#include <fenv.h> 401.8Sriastrad#include <signal.h> 411.1Schristos#include <stdio.h> 421.8Sriastrad#include <stdlib.h> 431.1Schristos#include <string.h> 441.1Schristos#include <unistd.h> 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.5Skamil { "trap", SIGTRAP }, 691.5Skamil { "ill", SIGILL }, 701.5Skamil { "fpe", SIGFPE }, 711.5Skamil { "bus", SIGBUS } 721.4Skamil}; 731.4Skamil 741.1Schristosstatic void 751.5Skamiltrigger_segv(void) 761.5Skamil{ 771.5Skamil volatile int *p = (int *)(intptr_t)atoi("0"); 781.5Skamil 791.5Skamil *p = 1; 801.5Skamil} 811.5Skamil 821.5Skamilstatic void 831.5Skamiltrigger_trap(void) 841.1Schristos{ 851.5Skamil 861.4Skamil#ifdef PTRACE_BREAKPOINT_ASM 871.5Skamil PTRACE_BREAKPOINT_ASM; 881.5Skamil#else 891.5Skamil /* port me */ 901.5Skamil#endif 911.5Skamil} 921.5Skamil 931.5Skamilstatic void 941.5Skamiltrigger_ill(void) 951.5Skamil{ 961.5Skamil 971.5Skamil#ifdef PTRACE_ILLEGAL_ASM 981.5Skamil PTRACE_ILLEGAL_ASM; 991.4Skamil#else 1001.5Skamil /* port me */ 1011.5Skamil#endif 1021.5Skamil} 1031.5Skamil 1041.5Skamilstatic void 1051.5Skamiltrigger_fpe(void) 1061.5Skamil{ 1071.9Sriastrad volatile double a = getpid(); 1081.9Sriastrad volatile double b = strtol("0", NULL, 0); 1091.5Skamil 1101.9Sriastrad feenableexcept(FE_ALL_EXCEPT); 1111.9Sriastrad 1121.9Sriastrad usleep((int)(a/b)); 1131.5Skamil} 1141.5Skamil 1151.5Skamilstatic void 1161.5Skamiltrigger_bus(void) 1171.5Skamil{ 1181.5Skamil FILE *fp; 1191.5Skamil char *p; 1201.5Skamil 1211.5Skamil /* Open an empty file for writing. */ 1221.5Skamil fp = tmpfile(); 1231.5Skamil if (fp == NULL) 1241.5Skamil err(EXIT_FAILURE, "tmpfile"); 1251.5Skamil 1261.7Skamil /* 1271.7Skamil * Map an empty file with mmap(2) to a pointer. 1281.7Skamil * 1291.7Skamil * PROT_READ handles read-modify-write sequences emitted for 1301.7Skamil * certain combinations of CPUs and compilers (e.g. Alpha AXP). 1311.7Skamil */ 1321.6Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 1331.5Skamil if (p == MAP_FAILED) 1341.5Skamil err(EXIT_FAILURE, "mmap"); 1351.5Skamil 1361.5Skamil /* Invalid memory access causes CPU trap, translated to SIGBUS */ 1371.5Skamil *p = 'a'; 1381.5Skamil} 1391.5Skamil 1401.5Skamilstatic void 1411.5Skamiltrigger(void) 1421.5Skamil{ 1431.5Skamil 1441.5Skamil switch (sig) { 1451.5Skamil case SIGSEGV: 1461.5Skamil trigger_segv(); 1471.5Skamil break; 1481.5Skamil case SIGTRAP: 1491.5Skamil trigger_trap(); 1501.5Skamil break; 1511.5Skamil case SIGILL: 1521.5Skamil trigger_ill(); 1531.5Skamil break; 1541.5Skamil case SIGFPE: 1551.5Skamil trigger_fpe(); 1561.5Skamil break; 1571.5Skamil case SIGBUS: 1581.5Skamil trigger_bus(); 1591.5Skamil break; 1601.5Skamil default: 1611.5Skamil break; 1621.4Skamil } 1631.5Skamil} 1641.5Skamil 1651.5Skamilstatic void 1661.5Skamilfoo(int s) 1671.5Skamil{ 1681.5Skamil char buf[64]; 1691.5Skamil int i = snprintf(buf, sizeof(buf), "got %d\n", s); 1701.5Skamil write(2, buf, i); 1711.5Skamil 1721.5Skamil if (flags & F_RECURSE) 1731.5Skamil trigger(); 1741.5Skamil 1751.5Skamil exit(EXIT_SUCCESS); 1761.1Schristos} 1771.1Schristos 1781.1Schristosstatic __dead void 1791.1Schristosusage(void) 1801.1Schristos{ 1811.4Skamil const char *pname = getprogname(); 1821.4Skamil 1831.5Skamil fprintf(stderr, "Usage: %s segv|trap|ill|fpe|bus " 1841.5Skamil "[recurse|mask|handle|ignore] ...\n", pname); 1851.5Skamil 1861.1Schristos exit(EXIT_FAILURE); 1871.1Schristos} 1881.1Schristos 1891.1Schristosint 1901.1Schristosmain(int argc, char *argv[]) 1911.1Schristos{ 1921.5Skamil 1931.1Schristos if (argc == 1) 1941.1Schristos usage(); 1951.1Schristos 1961.1Schristos for (int i = 1; i < argc; i++) { 1971.1Schristos size_t j; 1981.4Skamil for (j = 0; j < __arraycount(nv); j++) { 1991.1Schristos if (strcmp(nv[j].n, argv[i]) == 0) { 2001.1Schristos flags |= nv[j].v; 2011.5Skamil goto consumed; 2021.1Schristos } 2031.5Skamil } 2041.5Skamil for (j = 0; j < __arraycount(sn); j++) { 2051.4Skamil if (strcmp(sn[j].n, argv[i]) == 0) { 2061.4Skamil sig = sn[j].v; 2071.5Skamil goto consumed; 2081.4Skamil } 2091.4Skamil } 2101.5Skamil 2111.5Skamil usage(); 2121.5Skamil 2131.5Skamil consumed: 2141.5Skamil continue; 2151.1Schristos } 2161.1Schristos 2171.4Skamil if (flags == 0 || sig == 0) 2181.1Schristos usage(); 2191.1Schristos 2201.1Schristos if (flags & F_HANDLE) { 2211.1Schristos struct sigaction sa; 2221.1Schristos 2231.1Schristos sa.sa_flags = SA_RESTART; 2241.1Schristos sa.sa_handler = foo; 2251.1Schristos sigemptyset(&sa.sa_mask); 2261.4Skamil if (sigaction(sig, &sa, NULL) == -1) 2271.1Schristos err(EXIT_FAILURE, "sigaction"); 2281.1Schristos } 2291.1Schristos 2301.1Schristos if (flags & F_MASK) { 2311.1Schristos sigset_t set; 2321.1Schristos 2331.1Schristos sigemptyset(&set); 2341.4Skamil sigaddset(&set, sig); 2351.1Schristos if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) 2361.1Schristos err(EXIT_FAILURE, "sigprocmask"); 2371.1Schristos } 2381.1Schristos 2391.3Skamil if (flags & F_IGNORE) { 2401.3Skamil struct sigaction sa; 2411.3Skamil 2421.3Skamil memset(&sa, 0, sizeof(sa)); 2431.3Skamil sa.sa_handler = SIG_IGN; 2441.3Skamil sigemptyset(&sa.sa_mask); 2451.4Skamil if (sigaction(sig, &sa, NULL) == -1) 2461.3Skamil err(EXIT_FAILURE, "sigaction"); 2471.3Skamil } 2481.3Skamil 2491.5Skamil trigger(); 2501.5Skamil 2511.1Schristos return EXIT_SUCCESS; 2521.1Schristos} 253