plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 1 | /* |
| 2 | * crash01.c - Test OS robustness by creating a string of random bytes and then jump to it. |
| 3 | * |
| 4 | * New version Copyright (C) 2001 Stephane Fillod <f4cfe@free.fr> |
| 5 | * |
| 6 | * Original idea (c) 1990-1994 by GEORGE J. CARRETTE, CONCORD, MASSACHUSETTS. |
| 7 | * from crashme version: "2.4 20-MAY-1994" <GJC@WORLD.STD.COM> |
| 8 | */ |
| 9 | /* TODO: trapme: forge syscall with random args, and run it!! --SF */ |
| 10 | |
| 11 | /* |
| 12 | * COPYRIGHT (c) 1990-1994 BY * |
| 13 | * GEORGE J. CARRETTE, CONCORD, MASSACHUSETTS. * |
| 14 | * ALL RIGHTS RESERVED * |
| 15 | |
| 16 | Permission to use, copy, modify, distribute and sell this software |
| 17 | and its documentation for any purpose and without fee is hereby |
| 18 | granted, provided that the above copyright notice appear in all copies |
| 19 | and that both that copyright notice and this permission notice appear |
| 20 | in supporting documentation, and that the name of the author |
| 21 | not be used in advertising or publicity pertaining to distribution |
| 22 | of the software without specific, written prior permission. |
| 23 | |
| 24 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING |
| 25 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL |
| 26 | HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR |
| 27 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
| 28 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
| 29 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
| 30 | SOFTWARE. |
| 31 | |
| 32 | */ |
| 33 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 34 | /* |
| 35 | |
| 36 | A signal handler is set up so that in most cases the machine exception |
| 37 | generated by the illegal instructions, bad operands, etc in the procedure |
| 38 | made up of random data are caught; and another round of randomness may |
| 39 | be tried. Eventually a random instruction may corrupt the program or |
| 40 | the machine state in such a way that the program must halt. This is |
| 41 | a test of the robustness of the hardware/software for instruction |
| 42 | fault handling. |
| 43 | |
| 44 | Note: Running this program just a few times, using total CPU time of |
| 45 | less than a few seconds SHOULD NOT GIVE YOU ANY CONFIDENCE in system |
| 46 | robustness. Having it run for hours, with tens of thousands of cases |
| 47 | would be a different thing. It would also make sense to run this |
| 48 | stress test at the same time you run other tests, like a multi-user |
| 49 | benchmark. |
| 50 | |
| 51 | */ |
| 52 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 53 | #include <stdio.h> |
| 54 | #include <stdlib.h> |
| 55 | #include <string.h> |
| 56 | #include <signal.h> |
| 57 | #include <setjmp.h> |
| 58 | #include <time.h> |
| 59 | #include <unistd.h> |
| 60 | #include <sys/types.h> |
| 61 | #include <sys/wait.h> |
| 62 | |
| 63 | #include "test.h" |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 64 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 65 | char *TCID = "crash01"; |
| 66 | int TST_TOTAL = 1; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 67 | |
| 68 | static int x_opt = 0; |
| 69 | static int v_opt = 0; |
| 70 | static char *v_copt; |
| 71 | static int s_opt = 0; |
| 72 | static char *s_copt; |
| 73 | static int b_opt = 0; |
| 74 | static char *b_copt; |
| 75 | static int n_opt = 0; |
| 76 | static char *n_copt; |
| 77 | |
| 78 | int verbose_level = 2; |
| 79 | |
| 80 | /* Also, it may spend more time trapping and less time computing random bytes |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 81 | * by using the smallest incptr (while not executing already tested bits). |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 82 | */ |
| 83 | int incptr = 80; |
| 84 | |
| 85 | int nseed; |
| 86 | int ntries = 100; |
| 87 | |
| 88 | /* compute block of nbytes at a time */ |
| 89 | const int nbytes = 2000; |
| 90 | |
| 91 | /* max time allowed per try, in seconds */ |
| 92 | #define MAX_TRY_TIME 5 |
| 93 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 94 | /* in % */ |
| 95 | #define BLOCK_TRIGGER 80 |
| 96 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 97 | void cleanup() |
| 98 | { |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 99 | |
| 100 | tst_rmdir(); |
| 101 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | void setup() |
| 105 | { |
| 106 | /* |
| 107 | * setup a default signal hander and a |
| 108 | * temporary working directory. |
| 109 | */ |
| 110 | tst_sig(FORK, DEF_HANDLER, cleanup); |
| 111 | |
| 112 | tst_tmpdir(); |
| 113 | |
| 114 | TEST_PAUSE; |
| 115 | } |
| 116 | |
| 117 | void help() |
| 118 | { |
| 119 | printf(" -x dry run, hexdump random code instead\n"); |
| 120 | printf(" -v x verbose level\n"); |
| 121 | printf(" -s x random seed\n"); |
| 122 | printf(" -n x ntries\n"); |
| 123 | printf(" -b x inc\n"); |
| 124 | } |
| 125 | |
| 126 | /* |
| 127 | * crashme [+]<nbytes>[.inc] <srand> <ntries> [nsub] [verbose]" |
| 128 | * |
| 129 | * crashme <-b [+]<nbytes>[.inc]> <-s srand> <-n ntries> [-v verbose]" |
| 130 | * crashme +2000.80 666 100 1:10:30 2 |
| 131 | * nsub -> -c ? |
| 132 | */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 133 | option_t options[] = { |
| 134 | {"v:", &v_opt, &v_copt}, |
| 135 | {"s:", &s_opt, &s_copt}, |
| 136 | {"n:", &n_opt, &n_copt}, |
| 137 | {"b:", &b_opt, &b_copt}, |
| 138 | {"x", &x_opt, NULL}, |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 139 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 140 | {NULL, NULL, NULL} |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 141 | }; |
| 142 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 143 | int malloc_flag = 1; /* to be phased out */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 144 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 145 | void badboy_fork(); |
| 146 | void badboy_loop(); |
| 147 | void summarize_status(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 148 | void record_status(unsigned int n); |
| 149 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 150 | int main(int argc, char *argv[]) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 151 | { |
Cyril Hrubis | 0b9589f | 2014-05-27 17:40:33 +0200 | [diff] [blame] | 152 | const char *msg; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 153 | int lc; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 154 | |
Cyril Hrubis | cf0d626 | 2014-09-23 14:03:31 +0200 | [diff] [blame] | 155 | if ((msg = parse_opts(argc, argv, options, help)) != NULL) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 156 | tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 157 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 158 | if (v_opt) |
| 159 | verbose_level = atoi(v_copt); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 160 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 161 | if (n_opt) |
| 162 | ntries = atoi(n_copt); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 163 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 164 | if (s_opt) |
| 165 | nseed = atoi(s_copt); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 166 | else |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 167 | nseed = time(NULL); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 168 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 169 | if (b_opt) { |
| 170 | int inc; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 171 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 172 | inc = atoi(b_copt); |
| 173 | if (inc <= nbytes / 2) |
| 174 | incptr = inc; |
| 175 | else |
| 176 | tst_brkm(TBROK, cleanup, |
| 177 | "Invalid arg for -b (max: %u): %s", nbytes / 2, |
| 178 | b_copt); |
| 179 | } |
| 180 | |
| 181 | setup(); |
| 182 | |
| 183 | for (lc = 0; TEST_LOOPING(lc); lc++) { |
Caspar Zhang | d59a659 | 2013-03-07 14:59:12 +0800 | [diff] [blame] | 184 | tst_count = 0; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 185 | |
| 186 | tst_resm(TINFO, "crashme %s%d.%d %d %d", |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 187 | (malloc_flag == 0) ? "" : "+", nbytes, incptr, nseed, |
| 188 | ntries); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 189 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 190 | srand(nseed); |
| 191 | badboy_fork(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 192 | |
| 193 | /* still there? */ |
| 194 | tst_resm(TPASS, "we're still here, OS seems to be robust"); |
| 195 | |
| 196 | nseed++; |
| 197 | } |
| 198 | summarize_status(); |
| 199 | cleanup(); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 200 | tst_exit(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 201 | } |
| 202 | |
| 203 | /* ************************* */ |
| 204 | int badboy_pid; |
| 205 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 206 | void my_signal(int sig, void (*func) ()); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 207 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 208 | void monitor_fcn(int sig) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 209 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 210 | int status; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 211 | |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 212 | if (verbose_level >= 3) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 213 | printf("time limit reached on pid. using kill.\n"); |
| 214 | |
| 215 | status = kill(badboy_pid, SIGKILL); |
| 216 | if (status < 0) { |
| 217 | if (verbose_level >= 3) |
| 218 | printf("failed to kill process\n"); |
| 219 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 220 | } |
| 221 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 222 | void badboy_fork() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 223 | { |
| 224 | int status, pid; |
| 225 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 226 | status = fork(); |
| 227 | badboy_pid = status; |
| 228 | if (status == 0) { /* badboy */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 229 | #ifdef DEBUG_LATE_BADBOY |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 230 | sleep(ntries * MAX_TRY_TIME + 10); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 231 | #else |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 232 | badboy_loop(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 233 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 234 | exit(0); /* good goy, he survived! */ |
| 235 | } else if (status < 0) |
| 236 | perror("fork"); |
| 237 | else { /* parent watching over badboy */ |
| 238 | |
| 239 | if (verbose_level > 3) |
| 240 | printf("badboy pid = %d\n", badboy_pid); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 241 | |
| 242 | /* don't trust the child to return at night */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 243 | my_signal(SIGALRM, monitor_fcn); |
| 244 | alarm(ntries * MAX_TRY_TIME); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 245 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 246 | pid = wait(&status); |
| 247 | if (pid <= 0) { |
| 248 | perror("wait"); |
| 249 | } else { |
| 250 | if (verbose_level > 3) |
| 251 | printf("pid %d exited with status %d\n", pid, |
| 252 | status); |
| 253 | record_status(status); |
| 254 | } |
| 255 | } /* parent */ |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 256 | alarm(0); |
| 257 | } |
| 258 | |
| 259 | /* *************** status recording ************************* */ |
| 260 | |
| 261 | #define STATUS_MAX 256 |
| 262 | static int status_table[STATUS_MAX]; |
| 263 | |
| 264 | void record_status(unsigned int n) |
| 265 | { |
| 266 | if (n >= STATUS_MAX) |
| 267 | return; |
| 268 | |
| 269 | status_table[n]++; |
| 270 | } |
| 271 | |
| 272 | /* may not work with -c option */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 273 | void summarize_status() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 274 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 275 | int i; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 276 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 277 | if (verbose_level < 2) |
| 278 | return; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 279 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 280 | printf("exit status ... number of cases\n"); |
| 281 | for (i = 0; i < STATUS_MAX; i++) { |
| 282 | if (status_table[i]) |
| 283 | printf("%11d ... %5d\n", i, status_table[i]); |
| 284 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 285 | } |
| 286 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 287 | /* ************* badboy ******************************************* */ |
| 288 | |
| 289 | jmp_buf again_buff; |
| 290 | |
| 291 | typedef void (*BADBOY) (); |
| 292 | |
| 293 | BADBOY badboy; |
subrata_modak | b15aafd | 2008-10-20 06:30:32 +0000 | [diff] [blame] | 294 | char *the_data; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 295 | |
| 296 | int offset = 0; |
| 297 | int next_offset = 0; |
| 298 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 299 | char *bad_malloc(int n); |
| 300 | void my_signal(int sig, void (*func) ()); |
| 301 | void again_handler(int sig); |
| 302 | void compute_block_badboy(int n); |
| 303 | void compute_badboy(); |
| 304 | BADBOY castaway(char *dat); |
| 305 | void try_one_crash(); |
| 306 | void set_up_signals(); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 307 | |
| 308 | /* badboy "entry" point */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 309 | void badboy_loop() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 310 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 311 | int i; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 312 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 313 | if (malloc_flag == 0) { |
| 314 | the_data = bad_malloc((nbytes < 0) ? -nbytes : nbytes); |
| 315 | badboy = castaway(the_data); |
| 316 | printf("Badboy at %p\n", badboy); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 317 | } |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 318 | |
| 319 | for (i = 0; i < ntries; ++i) { |
| 320 | compute_badboy(); |
| 321 | /* level 5 */ |
| 322 | |
| 323 | if (!x_opt && verbose_level >= 5) { |
| 324 | if (offset) |
| 325 | printf("try %d, offset %d\n", i, offset); |
| 326 | else if (malloc_flag == 1) |
| 327 | printf("try %d, Badboy at %p\n", i, badboy); |
| 328 | else |
| 329 | printf("try %d\n", i); |
| 330 | } |
| 331 | |
| 332 | if (setjmp(again_buff) == 3) { |
| 333 | if (verbose_level >= 5) |
| 334 | printf("Barfed\n"); |
| 335 | } else { |
| 336 | set_up_signals(); |
| 337 | alarm(MAX_TRY_TIME); |
| 338 | try_one_crash(); |
| 339 | if (!x_opt && verbose_level >= 5) |
| 340 | printf("didn't barf!\n"); |
| 341 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 342 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 343 | } |
| 344 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 345 | char *bad_malloc(int n) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 346 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 347 | char *data; |
Cyril Hrubis | d218f34 | 2014-09-23 13:14:56 +0200 | [diff] [blame] | 348 | data = malloc(n); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 349 | #ifdef pyr |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 350 | if (mprotect(((int)data / PAGSIZ) * PAGSIZ, (n / PAGSIZ + 1) * PAGSIZ, |
| 351 | PROT_READ | PROT_WRITE | PROT_EXEC)) |
| 352 | perror("mprotect"); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 353 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 354 | return (data); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 355 | } |
| 356 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 357 | void again_handler(int sig) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 358 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 359 | char *ss; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 360 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 361 | switch (sig) { |
| 362 | case SIGILL: |
| 363 | ss = " illegal instruction"; |
| 364 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 365 | #ifdef SIGTRAP |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 366 | case SIGTRAP: |
| 367 | ss = " trace trap"; |
| 368 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 369 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 370 | case SIGFPE: |
| 371 | ss = " arithmetic exception"; |
| 372 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 373 | #ifdef SIGBUS |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 374 | case SIGBUS: |
| 375 | ss = " bus error"; |
| 376 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 377 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 378 | case SIGSEGV: |
| 379 | ss = " segmentation violation"; |
| 380 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 381 | #ifdef SIGIOT |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 382 | case SIGIOT: |
| 383 | ss = " IOT instruction"; |
| 384 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 385 | #endif |
| 386 | #ifdef SIGEMT |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 387 | case SIGEMT: |
| 388 | ss = " EMT instruction"; |
| 389 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 390 | #endif |
| 391 | #ifdef SIGALRM |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 392 | case SIGALRM: |
| 393 | ss = " alarm clock"; |
| 394 | break; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 395 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 396 | case SIGINT: |
| 397 | ss = " interrupt"; |
| 398 | break; |
| 399 | default: |
| 400 | ss = ""; |
| 401 | } |
| 402 | if (verbose_level >= 5) |
| 403 | printf("Got signal %d%s\n", sig, ss); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 404 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 405 | longjmp(again_buff, 3); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 406 | } |
| 407 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 408 | void my_signal(int sig, void (*func) ()) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 409 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 410 | struct sigaction act; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 411 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 412 | act.sa_handler = func; |
| 413 | memset(&act.sa_mask, 0x00, sizeof(sigset_t)); |
| 414 | act.sa_flags = SA_NOMASK | SA_RESTART; |
| 415 | sigaction(sig, &act, 0); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 416 | } |
| 417 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 418 | void set_up_signals() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 419 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 420 | my_signal(SIGILL, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 421 | #ifdef SIGTRAP |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 422 | my_signal(SIGTRAP, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 423 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 424 | my_signal(SIGFPE, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 425 | #ifdef SIGBUS |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 426 | my_signal(SIGBUS, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 427 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 428 | my_signal(SIGSEGV, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 429 | #ifdef SIGIOT |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 430 | my_signal(SIGIOT, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 431 | #endif |
| 432 | #ifdef SIGEMT |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 433 | my_signal(SIGEMT, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 434 | #endif |
| 435 | #ifdef SIGALRM |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 436 | my_signal(SIGALRM, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 437 | #endif |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 438 | my_signal(SIGINT, again_handler); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 439 | } |
| 440 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 441 | void compute_block_badboy(int n) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 442 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 443 | int j; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 444 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 445 | if (malloc_flag == 1) { |
| 446 | free(the_data); |
| 447 | the_data = bad_malloc(n); |
| 448 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 449 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 450 | for (j = 0; j < n; ++j) { |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 451 | #ifdef WANT_SLOW_RAND |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 452 | the_data[j] = 0xFF & (int)(256.0 * rand() / (RAND_MAX + 1.0)); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 453 | #else |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 454 | the_data[j] = (rand() >> 7) & 0xFF; |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 455 | #endif |
plars | 038e4bc | 2006-06-14 02:09:33 +0000 | [diff] [blame] | 456 | #ifdef __powerpc__ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 457 | __asm__ |
| 458 | __volatile__("dcbst 0,%0 ; icbi 0,%0 ; isync"::"r" |
| 459 | (&the_data[j])); |
plars | 038e4bc | 2006-06-14 02:09:33 +0000 | [diff] [blame] | 460 | #endif |
| 461 | |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 462 | } |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 463 | |
| 464 | /* was (nbytes < 0) */ |
| 465 | if (x_opt) { |
| 466 | if (verbose_level >= 1) |
| 467 | printf("Dump of %d bytes of data\n", n); |
| 468 | for (j = 0; j < n; ++j) { |
| 469 | if ((j % 16) == 0) |
| 470 | printf("\n%04d: ", j); |
| 471 | |
| 472 | printf("%02x ", the_data[j]); |
| 473 | } |
| 474 | putc('\n', stdout); |
| 475 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 476 | } |
| 477 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 478 | BADBOY castaway(char *dat) |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 479 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 480 | return ((BADBOY) dat); |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 481 | } |
| 482 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 483 | void compute_badboy() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 484 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 485 | if (incptr == 0) { |
| 486 | compute_block_badboy(nbytes); |
| 487 | badboy = castaway(the_data); |
| 488 | } |
| 489 | /* trigger block generation at xx % of the current block */ |
| 490 | else if ((next_offset == 0) |
| 491 | || (next_offset > ((nbytes * BLOCK_TRIGGER) / 100))) { |
| 492 | compute_block_badboy(nbytes); |
| 493 | offset = 0; |
| 494 | next_offset = offset + incptr; |
| 495 | badboy = castaway(the_data); |
| 496 | } else { |
| 497 | offset = next_offset; |
| 498 | next_offset = offset + incptr; |
| 499 | badboy = castaway(&the_data[offset]); |
| 500 | } |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 501 | } |
| 502 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 503 | void try_one_crash() |
plars | 865695b | 2001-08-27 22:15:12 +0000 | [diff] [blame] | 504 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 505 | /* was (nbytes < 0) */ |
| 506 | if (!x_opt) |
| 507 | (*badboy) (); |
| 508 | else if (nbytes == 0) |
| 509 | while (1) ; |
Chris Dearman | ec6edca | 2012-10-17 19:54:01 -0700 | [diff] [blame] | 510 | } |