crashme-2.8.5/ 0000775 0001750 0001750 00000000000 12370423713 011244 5 ustar gjc gjc crashme-2.8.5/descrip.mms 0000644 0001750 0001750 00000002446 12317647533 013430 0 ustar gjc gjc ! VMS MAKEFILE (for MMS)
!
all depends_on crashme.exe pddet.exe
!(ALL DONE)
crashme.exe depends_on crashme.obj
optarg = ",crashme.vms-opt/opt"
if f$getsyi("SID") .lt. 0 then optarg = ""
link crashme.obj'optarg'
! re-execute the next line in your superior process:
crashme == "$" + f$env("DEFAULT") + "CRASHME"
crashme.obj depends_on crashme.c
PF = ""
if f$getsyi("SID") .lt. 0 then PF = "/PREFIX=ALL"
CC/DEBUG/OPTIMIZE=(NOINLINE)'PF' CRASHME.C
pddet.exe depends_on pddet.obj
optarg = ",crashme.opt/opt"
if f$getsyi("SID") .lt. 0 then optarg = ""
link pddet.obj'optarg'
! re-execute the next line in your superior process:
pddet == "$" + f$env("DEFAULT") + "PDDET"
pddet.obj depends_on pddet.c
PF = ""
if f$getsyi("SID") .lt. 0 then PF = "/PREFIX=ALL"
CC/DEBUG/OPTIMIZE=(NOINLINE)'PF' PDDET.C
crashme_dbg.exe depends_on crashme.obj
optarg = ",crashme.opt/opt"
if f$getsyi("SID") .lt. 0 then optarg = ""
link/debug/exe=crashme_dbg.exe crashme.obj'optarg'
! note: do not use continuation character here.
DIST_FILES = crashme.1,crashme.c,makefile,descrip.mms,crashme.opt,read.me,shar.db,makefile.wnt,make.bat,pddet.c
crashme.shar depends_on $(DIST_FILES)
minishar crashme.shar shar.db
crashme.1_of_1 depends_on $(DIST_FILES)
define share_max_part_size 1000
vms_share $(DIST_FILES) crashme
crashme-2.8.5/pddet.c 0000664 0001750 0001750 00000042703 12370416647 012526 0 ustar gjc gjc /* -*- Mode: C; indent-tabs-mode: nil -*- */
/*
* COPYRIGHT (c) 1994 BY *
* GEORGE J. CARRETTE, CONCORD, MASSACHUSETTS. *
* ALL RIGHTS RESERVED *
Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all copies
and that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of the author
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
The purpose of this routine is to attempt to detect the use of
procedure descriptors by making a note of how far apart the
system allocates pointers to subroutines of different sizes.
If all the subroutines are the same distance apart then
procedure descriptors are probably in use on this architecture.
This file should be compiled without any compiler optimization
such as inlining that would confuse the test. Although base functions
have been made somewhat complex in order to avoid that in any case.
Now if a linker lays out procedures like this:
[DESCRIPTOR][CODE TEXT...][DESCRIPTOR][CODE TEXT...]
Then this code will be confused into thinking descriptors aren't used.
But usually the hallmark of a descriptor architecture is that descriptors
are in a table located away from the program code text.
The -examine argument lets you see in a crude way what
is contained in the pointer to a procedure data.
19-MAY-1994 GJC@WORLD.STD.COM
*/
#include
#include
#include
#ifdef WIN32
#include
#endif
struct v
{
long n;
double *a;
};
struct v *
vcons (n, x)
long n;
double x;
{
struct v *p;
long j;
p = (struct v *) malloc (sizeof (struct v));
p->n = n;
p->a = (double *) malloc (sizeof (double) * n);
for (j = 0; j < n; ++j)
p->a[j] = x;
return (p);
}
struct v *
vprod (x, y)
struct v *x, *y;
{
struct v *z;
long j;
z = vcons (x->n, 0.0);
for (j = 0; j < x->n; ++j)
z->a[j] = x->a[j] * y->a[j];
return (z);
}
double
vsume (x)
struct v *x;
{
double sum = 0.0;
long j;
for (j = 0; j < x->n; ++j)
sum += x->a[j];
return (sum);
}
double
viprod (x, y)
struct v *x, *y;
{
return (vsume (vprod (x, y)));
}
double
vnorm (x)
struct v *x;
{
return (viprod (x, x));
}
double
case10 ()
{
double acc = 0.0;
acc += vnorm (vcons ((long) vsume (vcons (0, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (1, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (2, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (3, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (4, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (5, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (6, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (7, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (8, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (9, 1.0)), 2.0));
return (acc);
}
double
case20 ()
{
double acc = 0.0;
acc += vnorm (vcons ((long) vsume (vcons (0, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (1, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (2, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (3, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (4, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (5, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (6, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (7, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (8, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (9, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (10, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (11, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (12, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (13, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (14, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (15, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (16, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (17, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (18, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (19, 1.0)), 2.0));
return (acc);
}
double
case30 ()
{
double acc = 0.0;
acc += vnorm (vcons ((long) vsume (vcons (0, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (1, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (2, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (3, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (4, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (5, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (6, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (7, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (8, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (9, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (10, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (11, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (12, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (13, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (14, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (15, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (16, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (17, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (18, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (19, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (20, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (21, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (22, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (23, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (24, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (25, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (26, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (27, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (28, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (29, 1.0)), 2.0));
return (acc);
}
double
case40 ()
{
double acc = 0.0;
acc += vnorm (vcons ((long) vsume (vcons (0, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (1, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (2, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (3, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (4, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (5, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (6, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (7, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (8, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (9, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (10, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (11, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (12, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (13, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (14, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (15, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (16, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (17, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (18, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (19, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (20, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (21, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (22, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (23, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (24, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (25, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (26, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (27, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (28, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (29, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (30, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (31, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (32, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (33, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (34, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (35, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (36, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (37, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (38, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (39, 1.0)), 2.0));
return (acc);
}
double
case50 ()
{
double acc = 0.0;
acc += vnorm (vcons ((long) vsume (vcons (0, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (1, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (2, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (3, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (4, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (5, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (6, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (7, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (8, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (9, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (10, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (11, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (12, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (13, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (14, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (15, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (16, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (17, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (18, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (19, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (20, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (21, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (22, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (23, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (24, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (25, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (26, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (27, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (28, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (29, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (30, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (31, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (32, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (33, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (34, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (35, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (36, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (37, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (38, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (39, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (40, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (41, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (42, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (43, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (44, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (45, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (46, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (47, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (48, 1.0)), 2.0));
acc += vnorm (vcons ((long) vsume (vcons (49, 1.0)), 2.0));
return (acc);
}
void
sayarch (x)
char *x;
{
printf ("This architecture %s procedure descriptors\n", x);
}
struct apair
{
char *name;
unsigned long addr;
};
struct adelt
{
long delta;
long count;
};
#ifndef WIN32
#define __cdecl
#endif
int __cdecl
apairl (const void *v_a, const void *v_b)
{
const struct apair *a = v_a;
const struct apair *b = v_b;
if (a->addr < b->addr)
return (-1);
else if (a->addr > b->addr)
return (1);
else
return (0);
}
int __cdecl
adeltl (const void *v_a, const void *v_b)
{
const struct adelt *a = v_a;
const struct adelt *b = v_b;
if (a->delta < b->delta)
return (-1);
else if (a->delta > b->delta)
return (1);
else
return (0);
}
#ifdef WIN32
void
describe_system_info(void)
{
/* %I64X */
SYSTEM_INFO si;
GetSystemInfo(&si);
printf ("%30s = %ld\n", "wProcessorArchitecture", (long) si.wProcessorArchitecture);
printf ("%30s = %ld\n", "wReserved;", (long) si.wReserved);
printf ("%30s = %ld\n", "dwPageSize", (long) si.dwPageSize);
printf ("%30s = 0x%016llX\n", "lpMinimumApplicationAddress", (long long) si.lpMinimumApplicationAddress);
printf ("%30s = 0x%016llX\n", "lpMaximumApplicationAddress", (long long) si.lpMaximumApplicationAddress);
printf ("%30s = 0x%lX\n", "dwActiveProcessorMask", (long) si.dwActiveProcessorMask);
printf ("%30s = %ld\n", "dwNumberOfProcessors", (long) si.dwNumberOfProcessors);
printf ("%30s = %ld\n", "dwProcessorType", (long) si.dwProcessorType);
printf ("%30s = %ld\n", "dwAllocationGranularity", (long) si.dwAllocationGranularity);
printf ("%30s = %ld\n", "wProcessorLevel", (long) si.wProcessorLevel);
printf ("%30s = 0x%lX\n", "wProcessorRevision", (long) si.wProcessorRevision);
}
#endif
int
main (argc, argv)
int argc;
char **argv;
{
struct apair all[10];
struct adelt deltas[10];
long j, k, n = 10, min_delta, max_delta, delta, d, ebytes = 0;
unsigned char *data, *prev_data;
printf ("Crashme(pddet): (c) Copyright 1990-2014 George J. Carrette\n");
printf ("From http://alum.mit.edu/www/gjc/crashme.html\n");
printf ("sizeof(char) = %ld\n", (long) sizeof (char));
printf ("sizeof(char *) = %ld\n", (long) sizeof (char *));
printf ("sizeof(int) = %ld\n", (long) sizeof (int));
printf ("sizeof(long) = %ld\n", (long) sizeof (long));
#ifdef WIN32
describe_system_info ();
#endif
for (j = 1; (j + 1) < argc; j += 2)
{
if (strcmp (argv[j], "-examine") == 0)
ebytes = atol (argv[j + 1]);
}
for (j = 0; j < n; ++j)
{
deltas[j].delta = 0;
deltas[j].count = 0;
}
all[0].name = "vcons";
all[0].addr = (unsigned long) vcons;
all[1].name = "vprod";
all[1].addr = (unsigned long) vprod;
all[2].name = "vsume";
all[2].addr = (unsigned long) vsume;
all[3].name = "viprod";
all[3].addr = (unsigned long) viprod;
all[4].name = "vnorm";
all[4].addr = (unsigned long) vnorm;
all[5].name = "case10";
all[5].addr = (unsigned long) case10;
all[6].name = "case20";
all[6].addr = (unsigned long) case20;
all[7].name = "case30";
all[7].addr = (unsigned long) case30;
all[8].name = "case40";
all[8].addr = (unsigned long) case40;
all[9].name = "case50";
all[9].addr = (unsigned long) case50;
if (ebytes > 0)
{
printf ("%10s %10s %s\n", "procedure", "address", "examine");
for (j = 0; j < n; ++j)
{
printf ("%10s %10ld ", all[j].name, (long) all[j].addr);
data = (unsigned char *) all[j].addr;
if (j > 0)
prev_data = (unsigned char *) all[j - 1].addr;
else
prev_data = NULL;
for (k = 0; k < ebytes; ++k)
if (prev_data && (prev_data[k] == data[k]))
printf ("..");
else
printf ("%02X", data[k]);
printf ("\n");
}
}
qsort (all, n, sizeof (struct apair), apairl);
printf ("%10s %10s %10s\n", "procedure", "address", "delta");
for (j = 0; j < n; ++j)
{
if (j > 0)
{
delta = all[j].addr - all[j - 1].addr;
if (j == 1)
min_delta = max_delta = delta;
else
{
if (delta < min_delta)
min_delta = delta;
if (delta > max_delta)
max_delta = delta;
}
for (k = 0; k < n; ++k)
if (deltas[k].count == 0)
{
deltas[k].delta = delta;
deltas[k].count = 1;
break;
}
else if (deltas[k].delta == delta)
{
++deltas[k].count;
break;
}
}
else
delta = 0;
printf ("%10s %10ld %10ld\n", all[j].name, (long) all[j].addr,
(long) delta);
}
printf ("min_delta = %ld, max_delta = %ld\n", (long) min_delta,
(long) max_delta);
if (min_delta == max_delta)
sayarch ("probably uses");
else
{
qsort (deltas, n, sizeof (struct adelt), adeltl);
printf ("%10s %s\n", "delta", "count");
for (d = 0, k = 0; k < n; ++k)
if (deltas[k].count > 0)
{
printf ("%10ld %ld\n", (long) deltas[k].delta,
(long) deltas[k].count);
++d;
}
if (d > 4)
sayarch ("probably does not use");
else
sayarch ("may be using");
}
return (EXIT_SUCCESS);
}
crashme-2.8.5/pddet.man 0000664 0001750 0001750 00000001161 12343061002 013025 0 ustar gjc gjc .TH PDDET 1
.SH NAME
pddet \- survey of procedure and descriptor usage
.SH DESCRIPTION
.I pddet
Survey of Procedure Descriptor Usage. The emphasis here is on
currently shipping products. The program pddet included
with the crashme distribution can be used to determine some of this
information. Note that in some environments, e.g. Microsoft C++ 4.0
the results of pddet will be different depending on the compilation
modes chosen: debug versus release.
.SH AUTHOR
George J Carrette. GJC\@alum.mit.edu
http://people.delphiforums.com/gjc/crashme.html
http://crashme.codeplex.com/
.SH VERSION
2.8.3 2-JUN-2014
crashme-2.8.5/makefile 0000644 0001750 0001750 00000012730 12370420410 012734 0 ustar gjc gjc
# unix makefile for crashme program.
CCFLAGS=-DPRNG_MT $(CFLAGS) $(LDFLAGS) $(CPPFLAGS)
DIST_VERSION=2.8.5
all: crashme pddet
# make "CFLAGS=-Wall -DPRNG_MT -g"xo CC=gcc
crashme: crashme.o vnsq.o mt19937ar.o
$(CC) $(CCFLAGS) -o crashme crashme.o vnsq.o mt19937ar.o
crashme.o: crashme.c
$(CC) $(CCFLAGS) -c crashme.c
pddet: pddet.o
$(CC) $(CCFLAGS) -o pddet pddet.o
pddet.o: pddet.c
$(CC) $(CCFLAGS) -c pddet.c
vnsq.o: vnsq.c
$(CC) $(CCFLAGS) -c vnsq.c
mt19937ar.o: mt19937ar.c
$(CC) $(CCFLAGS) -c mt19937ar.c
showdefs:
$(CC) -dM -E - < /dev/null
clean:
-rm crashme pddet *.o core crashme.zip \
crashme.tgz crashme_i386.zip *.plg *.ncb *.opt
-rm -rf release debug test-dist-tgz crashme-$(DIST_VERSION)
# create for dist for people without nroff
crashme.txt: crashme.man
nroff -man crashme.man | col -bx > crashme.txt
pddet.txt: pddet.man
nroff -man pddet.man | col -bx > pddet.txt
DIST_FILES = crashme.man crashme.c crashme.html \
crashme.vms-opt descrip.mms makefile \
pddet.c crashme.txt mt19937ar.h vnsq.h \
vnsq.c mt19937ar.c pddet.man pddet.txt
# These files were in the distribution.
# but they got lost and it isn't clear
# crashme.dsw crashme.dsp pddet.dsp
crashme.zip: $(DIST_FILES)
zip -D -j crashme.zip $(DIST_FILES)
crashme.tgz: $(DIST_FILES)
tar cvf - $(DIST_FILES) | gzip -v > crashme.tgz
check:
#nsgmls -s crashme.html
xmllint --noout crashme.html
xmllint --noout downloads.html
TAGS_SRC=$(DIST_FILES) downloads.html
TAGS: $(TAGS_SRC)
etags $(TAGS_SRC)
dist: crashme.zip crashme.tgz
dist-version: crashme-$(DIST_VERSION).tgz
crashme-$(DIST_VERSION).tgz: $(DIST_FILES)
rm -rf crashme-$(DIST_VERSION)
mkdir crashme-$(DIST_VERSION)
cp -a $(DIST_FILES) crashme-$(DIST_VERSION)
tar cvfz crashme-$(DIST_VERSION).tgz crashme-$(DIST_VERSION)
#crashme_i386.zip
CRASHME_I386=release/crashme.exe release/pddet.exe
crashme_i386.zip: $(DIST_FILES) $(CRASHME_I386)
zip -D -j crashme_i386.zip $(DIST_FILES) $(CRASHME_I386)
test-dist: crashme.tgz
(rm -rf test-dist-tgz;\
mkdir test-dist-tgz;\
cd test-dist-tgz;\
tar xvfz ../crashme.tgz;\
make all dist ptest1 ptest7)
test-dist-version: dist-version
(cd crashme-$(DIST_VERSION);\
make all dist ptest1 ptest7)
####
LOG_DIR=logs
# This directory is in Apple Mac Darwin.
# It will fill up with junk and probably really
# slow down things unless you turn off crash reporting
# for crashme.
LOG_DIR2=$$HOME/Library/Logs/DiagnosticReports
showcrashlogs:
ls $(LOG_DIR)
if [ -d $(LOG_DIR2) ]; then ls $(LOG_DIR2); fi
ptest1:
./pddet
ptest2:
./crashme 100 666 100
ptest3:
./crashme 100 667 100
ptest4:
mkdir -p $(LOG_DIR)
sh -c "CRASHPRNG=RAND;export CRASHPRNG;CRASHLOG=$(LOG_DIR)/crashme-ptest4.log;export CRASHLOG;./crashme 100 666 100"
ptest5:
./crashme -100 666 100
ptest6:
@echo This tests alarm clock
@echo you can also use control-C
./crashme 0 666 3
ptest7:
./crashme +256 666 10 3
ptest8:
./crashme +256 666 10 3 4
ptest9:
./crashme +256 666 100 3 4
ptest10:
./crashme +4096 666 100 00:00:05 4
ptest11:
./crashme +4096 666 250 00:03:00 4
# here are some tests taken from the BAT files done for windows.
test1: test1a test1b test1c
test1a:
mkdir -p $(LOG_DIR)
./pddet -examine 16
./pddet -examine 16 > $(LOG_DIR)/pddet.log
test1b:
sh -c "CRASHPRNG=MT;export CRASHPRNG;./crashme -64 666 5 -15 3" > $(LOG_DIR)/crashme-prng_mt.log
sh -c "CRASHPRNG=RAND;export CRASHPRNG;./crashme -64 666 5 -15 3" > $(LOG_DIR)/crashme-prng_rand.log
sh -c "CRASHPRNG=VNSQ;export CRASHPRNG;./crashme -64 666 5 -15 3" > $(LOG_DIR)/crashme-prng_vnsq.log
test1c: test1ca test1cb test1cc
test1ca:
sh -c "CRASHPRNG=MT;export CRASHPRNG;CRASHLOG=$(LOG_DIR)/crashme-test1-mt.log;export CRASHLOG;./crashme 8192 666 100 00:00:30 3"
test1cb:
sh -c "CRASHPRNG=RAND;export CRASHPRNG;CRASHLOG=$(LOG_DIR)/crashme-test1-rand.log;export CRASHLOG;./crashme 8192 666 100 00:00:30 3"
test1cc:
sh -c "CRASHPRNG=VNSQ;export CRASHPRNG;CRASHLOG=$(LOG_DIR)/crashme-test1-vnsq.log;export CRASHLOG;./crashme 8192 666 100 00:00:30 3"
test-mt19937ar: mt19937ar_main
./mt19937ar_main
mt19937ar_main: mt19937ar.c
$(CC) $(CCFLAGS) -DMT19937AR_MAIN -o mt19937ar_main mt19937ar.c
### Use these targets to disable all crash report generation,
### otherwise large amounts of system resources could be consumed.
### These targets are for Apple Mac.
report-crash-stop:
-launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
-sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
report-crash-start:
-launchctl load -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
-sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
### These commands work in some linux environments.
### An alternative would configuration of ~/.apport-ignore.xml or /etc/apport
### to tell apport to ignore crashme. But that still that leaves
### /proc/sys/kernel/core_pattern
### sending a large number of crash dumps to apport.
APPORT_INIT=/etc/init.d/apport
CORE_PATTERN_API=/proc/sys/kernel/core_pattern
CORE_PATTERN=core-%p-%u-%g-%s-%t-%h-%e
apport-crash-stop:
sudo $(APPORT_INIT) stop
cat $(CORE_PATTERN_API)
apport-crash-start:
sudo $(APPORT_INIT) start
cat $(CORE_PATTERN_API)
set-core-pattern:
sudo sh -c 'echo $(CORE_PATTERN) > $(CORE_PATTERN_API)'
cat $(CORE_PATTERN_API)
show-core-limit:
bash -c "ulimit -a"
#
ps:
-ps -C crashme -f -H
pgrep:
-pgrep -l crashme
pkill:
-pkill crashme
crashme-2.8.5/mt19937ar.c 0000644 0001750 0001750 00000014401 12317647533 012777 0 ustar gjc gjc /*
A C-program for MT19937, with initialization improved 2002/1/26.
Coded by Takuji Nishimura and Makoto Matsumoto.
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Any feedback is very welcome.
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/
#include
#include "mt19937ar.h"
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
static unsigned long mt[N]; /* the array for the state vector */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
/* initializes mt[N] with a seed */
void init_genrand(unsigned long s)
{
mt[0]= s & 0xffffffffUL;
for (mti=1; mti> 30)) + mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= 0xffffffffUL;
/* for >32 bit machines */
}
}
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
void init_by_array(unsigned long init_key[], int key_length)
{
int i, j, k;
init_genrand(19650218UL);
i=1; j=0;
k = (N>key_length ? N : key_length);
for (; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+ init_key[j] + j; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++; j++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
if (j>=key_length) j=0;
}
for (k=N-1; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
- i; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
}
mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
}
/* generates a random number on [0,0xffffffff]-interval */
unsigned long genrand_int32(void)
{
unsigned long y;
static unsigned long mag01[2]={0x0UL, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
if (mti >= N) { /* generate N words at one time */
int kk;
if (mti == N+1) /* if init_genrand() has not been called, */
init_genrand(5489UL); /* a default initial seed is used */
for (kk=0;kk> 1) ^ mag01[y & 0x1UL];
}
for (;kk> 1) ^ mag01[y & 0x1UL];
}
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
mti = 0;
}
y = mt[mti++];
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
/* generates a random number on [0,0x7fffffff]-interval */
long genrand_int31(void)
{
return (long)(genrand_int32()>>1);
}
/* generates a random number on [0,1]-real-interval */
double genrand_real1(void)
{
return genrand_int32()*(1.0/4294967295.0);
/* divided by 2^32-1 */
}
/* generates a random number on [0,1)-real-interval */
double genrand_real2(void)
{
return genrand_int32()*(1.0/4294967296.0);
/* divided by 2^32 */
}
/* generates a random number on (0,1)-real-interval */
double genrand_real3(void)
{
return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
/* divided by 2^32 */
}
/* generates a random number on [0,1) with 53-bit resolution*/
double genrand_res53(void)
{
unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
/* These real versions are due to Isaku Wada, 2002/01/09 added */
#ifdef MT19937AR_MAIN
int main(void)
{
int i;
unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4;
init_by_array(init, length);
printf("1000 outputs of genrand_int32()\n");
for (i=0; i<1000; i++) {
printf("%10lu ", genrand_int32());
if (i%5==4) printf("\n");
}
printf("\n1000 outputs of genrand_real2()\n");
for (i=0; i<1000; i++) {
printf("%10.8f ", genrand_real2());
if (i%5==4) printf("\n");
}
return 0;
}
#endif
crashme-2.8.5/crashme.vms-opt 0000644 0001750 0001750 00000000124 12317647533 014221 0 ustar gjc gjc ! VMS LINKER OPTIONS FILE
IDENTIFICATION = "CRASHME V1.8"
SYS$LIBRARY:VAXCRTL/SHARE
crashme-2.8.5/crashme.txt 0000644 0001750 0001750 00000012147 12370422750 013432 0 ustar gjc gjc CRASHME(1) General Commands Manual CRASHME(1)
NAME
crashme - test operating environment software robustness
SYNOPSIS
crashme [NBYTES] [SRAND] [NTRYS] [NSUB] [VERBOSE]
DESCRIPTION
crashme is a very simple program that tests the operating environment's
robustness by invoking random data as if it were a procedure. The
standard signals are caught and handled with a setjmp back to a loop
which will try again to produce a fault by executing random data. Some
people call this stress testing.
COMMAND LINE OPTIONS
[NBYTES]
The [NBYTES] should be an integer, specifying the size of the
random data string in bytes. If given negative then the bytes
are printed instead of being executed. If given with an
explicit plus sign then the storage for the bytes is freshly
malloc'ed each time. This can have an effect on machines with
separate I and D cache mechanisms. The argument can also have a
dot in it, X.Y, in which case Y is a increment for a pointer
into the random data. The buffer is recalculated only when the
pointer gets near the end of the data.
The are two magic values for [NBYTES] : A value of 81920 avoids
malloc and returns a pointer to static data. This makes the
operation of crashme more repeatable on architectures where
malloc is designed to return unpredictable locations. A value
of 1025 avoids a call that sets the protection of the data to
READ+WRITE+EXEC.
[SRAND] The [SRAND] is an input seed to the random number generator,
passed to srand.
[NTRIES]
The [NTRIES] is how many times to loop before exiting normally
from the program.
[NSUB] The [NSUB] is optional, the number of vfork subprocesses run‐
ning all at once. If negative run one after another. If given
as a time hrs:mns:scs (hours, minutes, seconds) then one sub‐
process will be run to completion, followed by another, until
the time limit has been reached. If this argument is given as
the empty string or . then it is ignored.
When in sequential-subprocess mode there is a 30 second time
limit on each subprocess. This is to allow the instruction-set-
space random walk to continue when a process bashes itself into
an infinite loop. For example, the ntrys can be bashed to a
very large number with nbytes bashed to zero. (10 second limit
on Windows NT).
The SRAND argument is incremented by one for each subprocess.
[VERBOSE]
The [VERBOSE] arg is optional. 0 is the least verbose, 5 the
most.
ENVIRONMENT VARIABLES
CRASHLOG
The CRASHLOG is the name of the file which the parent process
opens in write mode and all child processes open in append
mode. There is frequent flushing of the file but no locking, so
the output may be interleaved. If the operating system crashes
then this file might provide a short-cut to a more resent ran‐
dom number seed sequence to allow for quicker finding of the
special case that caused the crash.
CRASHPRNG
The CRASHPRNG can be set to RAND to use the system-provided
rand function, or MT to use the Mersenne twister (default) as
coded by Takuji Nishimura and Makoto Matsumoto, or VNSQ to use
the author's kludge interpretation of Von Neumann's middle-
square method.
EXAMPLE
This is a suggested test, to run it for a least an hour.
crashme +2000 666 100 1:00:00
FILES
crashme.c
DIAGNOSTICS
When a signal is caught the number and nature of the signal is indi‐
cated. Setting the environment variable CRASHLOG will cause each sub‐
process to record the arguments it was given.
BUGS
Not all signals are caught, and the state of the user program/process
environment can be sufficiently damaged such that the program termi‐
nates before going through all [NTRIES] operations.
If the architecture uses some kind of procedure descriptor but no spe‐
cial code has been not been added to castaway() in crashme.c then the
stress test will not be as potent as it would otherwise be.
Beware: This program can crash your computer if the operating system or
hardware of same is buggy. User data may be lost.
AUTHOR
George J Carrette. GJC@alum.mit.edu http://people.delphifo‐
rums.com/gjc/crashme.html http://crashme.codeplex.com/
VERSION
2.8.5 6-AUG-2014
CRASHME(1)
crashme-2.8.5/pddet.txt 0000664 0001750 0001750 00000001516 12343065454 013114 0 ustar gjc gjc PDDET(1) General Commands Manual PDDET(1)
NAME
pddet - survey of procedure and descriptor usage
DESCRIPTION
pddet Survey of Procedure Descriptor Usage. The emphasis here is on
currently shipping products. The program pddet included with the
crashme distribution can be used to determine some of this information.
Note that in some environments, e.g. Microsoft C++ 4.0 the results of
pddet will be different depending on the compilation modes chosen:
debug versus release.
AUTHOR
George J Carrette. GJC@alum.mit.edu http://people.delphifo‐
rums.com/gjc/crashme.html http://crashme.codeplex.com/
VERSION
2.8.3 2-JUN-2014
PDDET(1)
crashme-2.8.5/crashme.c 0000664 0001750 0001750 00000102124 12370422601 013025 0 ustar gjc gjc /* -*- Mode: C; indent-tabs-mode: nil -*- */
/* crashme: Create a string of random bytes and then jump to it.
crashme [+][.inc] [nsub] [verboseness] */
char *crashme_version = "2.8.5 6-AUG-2014";
/*
* COPYRIGHT (c) 1990-2014 BY *
* GEORGE J. CARRETTE, CONCORD, MASSACHUSETTS. *
* ALL RIGHTS RESERVED *
Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all copies
and that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of the author
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
A signal handler is set up so that in most cases the machine exception
generated by the illegal instructions, bad operands, etc in the procedure
made up of random data are caught; and another round of randomness may
be tried. Eventually a random instruction may corrupt the program or
the machine state in such a way that the program must halt. This is
a test of the robustness of the hardware/software for instruction
fault handling.
Note: Running this program just a few times, using total CPU time of
less than a few seconds SHOULD NOT GIVE YOU ANY CONFIDENCE in system
robustness. Having it run for hours, with tens of thousands of cases
would be a different thing. It would also make sense to run this
stress test at the same time you run other tests, like a multi-user
benchmark.
Comments may be addressed to the author at GJC@ALUM.MIT.EDU
See the documentation in crashme.1 and READ.ME, or read this code for
a description of command line arguments to this program.
Version Date Description
----------------------------------------------------------------------
1.0 early 1990 initial hack.
1.1 19-SEP-1990 added more signals and an alarm to abort looping.
1.2 25-JUN-1991 added [nsub] to vfork multiple subprocesses of self.
1.3 14-AUG-1991 +nbytes malloc option, and -nsub option.
1.4 29-AUG-1991 fix +nbytes (subproc). Add time-driven nprocs. SIGINT.
1.5 3-SEP-1991 added alarm subprocess monitor to vfork_main.
1.6 5-SEP-1991 some systems don't have vfork, so use fork by default.
1.7 25-SEP-1991 verboseness level, exit summary report.
1.8 -SEP-1991 address page protection issues on badboy.
1.9 6-AUG-1993 DECC(VMS)/WIN32/NT/Posix, #ifdef some SIGxxx.
2.0 7-SEP-1993 More extensive WIN32 conditionalization. record_note.
2.1 6-MAY-1994 Added "dot" syntax to NBYTES. Modularized castaway.
2.2 9-MAY-1994 __ALPHA && VMS version is now more interesting.
2.3 11-MAY-1994 Added _IBMRT2 and _POWER code.
2.4 20-MAY-1994 Added __hpux. Linux from jik@cam.ov.com.
2.5 6-JUL-2008 more WIN32 support
2.6 12-JUL-2008 use Mersenne twister pseudorandom number generator.
2.7 4-APR-2014 __APPLE__ port, fix linux 64 bit port.
2.8 22-MAY-2014 Magic NBYTES of 81920 and 1025.
2.8.1 27-MAY-2014 Debian patch to use execlp instead of execl
2.8.2 29-MAY-2014 fix bug in call to memset.
2.8.3 2-JUN-2014 gnu indent
2.8.4 10-JUN-2014 Microsoft Windows 64-bit Upgrade.
2.8.5 6-AUG-2014 bugs.debian.org bug=755759 struct sigaction
Suggested test: At least let the thing run the length of your lunch break,
in this case 1 hour, 10 minutes, and 30 seconds.
crashme +2000 666 100 1:10:30 2
Also, it may spend more time trapping and less time computing random bytes
by using these arguments:
crashme +2000.80 666 100 1:10:30 2
CRASH REPORTS
Date, Machine Crashme Reported
Crashme Ver Make Model OS Version Arguments by:
------------------------------------------------------------------------------
10-JUL-90 1.0 SUN 4/110 4.1 1000 20 200 GJC@paradigm.com
10-JUL-90 1.0 SUN 4/280 4.0.3 1000 20 200 GJC@paradigm.com
31-JUL-90 1.0 DIGITAL DECstation 3100 100 10 10000 GAVRON@ARIZONA.EDU
31-JUL-90 1.0 IBM RT 100 10 10000 GAVRON@ARIZONA.EDU
1-AUG-90 1.0 DIGITAL DECstation 5000 10000 230 1000 hudgens@scri.fsu.edu
3-AUG-90 1.0 Alliant FX/2800 SJA@SIRIUS.HUT.FI
27-JUN-91 1.2 SUN 4/110 4.1.1 10 1000 10 LPH@PARADIGM.COM
27-JUN-91 1.2 SUN 4/110 4.1.1 1000 20 200 10 LPH@PARADIGM.COM
29-JUN-91 1.2 SUN 4/40C 4.1.1 9 29748 5877 4 jon@uk.ac.oxford.robots
29-JUN-91 1.2 SUN 4/60 4.1.1 9 29748 5877 4 jon@uk.ac.oxford.robots
29-JUN-91 1.2 SUN 4/100 4.1.1 9 29748 5877 4 jon@uk.ac.oxford.robots
29-JUN-91 1.2 SUN 4/65 4.1.1 9 29748 5877 4 jon@uk.ac.oxford.robots
18-JUL-91 1.2 SGI Iris4d Unix 3.3.2 1000 $$ 1000 4 tsacas@ilog.ilog.fr
29-JUL-91 1.1 IBM RS/6000 AIX 1.3 script brandis@inf.ethz.ch
5-SEP-91 1.6 IBM RS/6000-320 AIX 3.1.5 +2000 666 50 40:00:00 LPH
26-SEP-91 1.8 Nixdorf Targon/35 TOS3.3 script petri@ibr.cs.tu-bs.de
9-SEP-93 2.0 Microsoft WNT Build 511 i486 +1000 24131 50 gjc@mitech.com
3-FEB-94 1.8 HP710/HP-UX 9.00 +2000 666 100 2:00:00 5 UFOP@fpsp.fapesp.br
5-MAY-94 2.0 HP807/HPUX 9.00 4000 666 100 00:30:00 2 UFOP@fpsp.fapesp.br
6-AUG-14 2.8 UBUNTU LTS 14.04 make set-core-pattern ptest11 gjc@alum.mit.edu
Notes: Crashme V1.0 {1000 20 200} used to down the SUN 4/110. V1.2 does *not*
crash SUNOS 4.1.1 on the same arguments. Although using the extra argument
for subprocesses it will crash, with the console reporting:
"Bad Trap, Bad Kernel Read Fault, Bus error. Reboot"
Script means invoking file with many calls to crashme such as this:
#/bin/csh
crashme 1020 234 500 &
crashme 394 38484 5723 &
crashme 3784 474 474 &
crashme 437 4747 38 &
crashme 47848 4745 123 &
crashme 4747 4747 3463 &
crashme 474 46464 262 &
crashme 37 3644 3723 &
crashme 374 46464 22 &
crashme 3747 464 363 &
crashme 347 4747 44 &
crashme 37374 374 66 &
crashme 3737 474 4444 &
The 4-argument case of crashme could likely do as well as executing
a script.
*/
#include
#include
#include
#ifdef WIN32
#include
#include
#else
#include
#include
#endif
#include
#ifdef VMS
#include
#endif
#ifdef pyr
#include
#include
#include
#include
#define strchr index
#endif
#ifdef linux
#include
#include
#endif
#if defined(__APPLE__) || defined(__FreeBSD__)
/* i am using XCODE command line tools under Lion */
#include
#include
#include
#endif
#ifdef WIN32
#else
#define _strdup strdup
#endif
void prng_setup (long nseed);
#define PRNG_TYPE_RAND 1
#define PRNG_TYPE_MT 2
#define PRNG_TYPE_VNSQ 3
int prng_type;
#ifdef PRNG_MT
#define PRNG_DEFAULT PRNG_TYPE_MT
#include "mt19937ar.h"
#else
#define PRNG_DEFAULT PRNG_TYPE_RAND
#endif
#include "vnsq.h"
typedef void (*BADBOY) ();
BADBOY badboy;
long nbytes, nseed, ntrys;
long incptr = 0;
long offset = 0;
long next_offset = 0;
long malloc_flag = 0;
unsigned char *the_data;
#define NOTE_BUFFER_LEN 1024
char *note_buffer;
char *notes;
long verbose_level = 5;
long child_kill_count = 0;
void old_main (int argc, char **argv);
void copyright_note (long n);
void vfork_main (long tflag, long nsubs, char *cmd, char *nb, long sr,
char *nt);
void badboy_loop (void);
char *subprocess_ind = "subprocess";
int subprocess_flag = 0;
/* Strictly speaking there should be an interlock on the log file
when it is being written to by multiple processes, but the overhead of
that would interfer with the behavior of crashme, and for the most part
the fflush is good enough to help us sort out any result */
int vfork_flag = 0;
FILE *logfile = NULL;
char *logfilename = NULL;
int note_count = 0;
void
record_note (void)
{
if (logfile && (note_count > 0))
{
fflush (logfile);
if ((subprocess_flag == 0) && (vfork_flag == 1))
{
/* we have children. Closing and opening the file will provide a bit
better output, avoiding the mixup, and without the complexity of
a lock. */
fclose (logfile);
logfile = fopen (logfilename, "a");
}
}
note_count = 0;
}
void
open_record (void)
{
char *tmp;
if ((!(tmp = getenv ("CRASHLOG"))) || (strcmp (tmp, "") == 0))
return;
logfilename = _strdup (tmp);
if (!(logfile = fopen (logfilename, (subprocess_flag) ? "a" : "w")))
{
perror (logfilename);
return;
}
}
void
close_record (void)
{
if (logfile)
{
fclose (logfile);
logfile = NULL;
}
}
void
note (long level)
{
if (level > verbose_level)
return;
++note_count;
strcat (note_buffer, "\n");
fputs (note_buffer, stdout);
fflush (stdout);
if (logfile)
{
fputs (note_buffer, logfile);
fflush (logfile);
}
}
#ifndef WIN32
jmp_buf again_buff;
#endif
#define MAGIC_NBYTES_STATIC 81920
#define MAGIC_NBYTES_NOEXEC 1025
unsigned char static_data[MAGIC_NBYTES_STATIC];
void
set_exec_prot (unsigned char *data, long n)
{
#ifdef pyr
if (mprotect (((int) data / PAGSIZ) * PAGSIZ, (n / PAGSIZ + 1) * PAGSIZ,
PROT_READ | PROT_WRITE | PROT_EXEC))
perror ("mprotect");
#endif
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(linux)
/* if we don't do this on the 64-bit architectures
then all we get out of our badboy() calls
is a nice safe "bus error" signal.
*/
int pagesize;
pagesize = getpagesize ();
if (mprotect ((void *) ((((long) data) / pagesize) * pagesize),
((n / pagesize) + 1) * pagesize,
PROT_READ | PROT_WRITE | PROT_EXEC))
perror ("mprotect");
#endif
}
unsigned char *
bad_malloc (long n)
{
unsigned char *data;
if ((malloc_flag == 0) && (n == sizeof (static_data)))
{
data = &static_data[0];
}
else
{
#ifdef WIN32
data = VirtualAlloc (NULL,
(SIZE_T) n,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (data == NULL) {
fprintf (stderr, "VirtualAlloc Failed %ld\n", (long) GetLastError ());
return(data);
}
#else
data = (unsigned char *) malloc (n);
#endif
}
if (data == NULL)
{
perror ("malloc");
return (NULL);
}
if (n != MAGIC_NBYTES_NOEXEC)
{
set_exec_prot (data, n);
}
return (data);
}
#ifndef WIN32
void
again_handler (int sig)
{
char *ss;
switch (sig)
{
case SIGILL:
ss = " illegal instruction";
break;
#ifdef SIGTRAP
case SIGTRAP:
ss = " trace trap";
break;
#endif
case SIGFPE:
ss = " arithmetic exception";
break;
#ifdef SIGBUS
case SIGBUS:
ss = " bus error";
break;
#endif
case SIGSEGV:
ss = " segmentation violation";
break;
#ifdef SIGIOT
case SIGIOT:
ss = " IOT instruction";
break;
#endif
#ifdef SIGEMT
case SIGEMT:
ss = " EMT instruction";
break;
#endif
#ifdef SIGALRM
case SIGALRM:
ss = " alarm clock";
break;
#endif
case SIGINT:
ss = " interrupt";
break;
default:
ss = "";
}
sprintf (notes, "Got signal %d%s", sig, ss);
note (5);
longjmp (again_buff, 3);
}
void
my_signal (int sig, void (*func) ())
{
#ifndef SA_ONESHOT
signal (sig, func);
#else
struct sigaction act;
memset (&act, 0, sizeof (act));
act.sa_handler = func;
act.sa_flags = SA_NOMASK;
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART;
#endif
sigaction (sig, &act, 0);
#endif /* SA_ONESHOT */
}
void
set_up_signals (void)
{
my_signal (SIGILL, again_handler);
#ifdef SIGTRAP
my_signal (SIGTRAP, again_handler);
#endif
my_signal (SIGFPE, again_handler);
#ifdef SIGBUS
my_signal (SIGBUS, again_handler);
#endif
my_signal (SIGSEGV, again_handler);
#ifdef SIGIOT
my_signal (SIGIOT, again_handler);
#endif
#ifdef SIGEMT
my_signal (SIGEMT, again_handler);
#endif
#ifdef SIGALRM
my_signal (SIGALRM, again_handler);
#endif
my_signal (SIGINT, again_handler);
}
#endif
void
compute_badboy_1 (long n)
{
long j;
if (malloc_flag == 1)
the_data = bad_malloc (n);
switch (prng_type)
{
case PRNG_TYPE_MT:
#ifdef PRNG_MT
for (j = 0; (j + 3) < n; j += 4)
{
unsigned long u = genrand_int32 ();
the_data[j + 0] = (u >> 24) & 0xFF;
the_data[j + 1] = (u >> 16) & 0xFF;
the_data[j + 2] = (u >> 8) & 0xFF;
the_data[j + 3] = (u >> 0) & 0xFF;
}
#endif
break;
case PRNG_TYPE_RAND:
for (j = 0; j < n; ++j)
the_data[j] = (rand () >> 7) & 0xFF;
break;
case PRNG_TYPE_VNSQ:
for (j = 0; (j + 1) < n; j += 2)
{
unsigned long u1 = vnsq_int32 ();
the_data[j + 0] = (u1 >> 1) & 0xFF;
the_data[j + 1] = (u1 >> 9) & 0xFF;
}
break;
default:
break;
}
if (nbytes < 0)
{
sprintf (notes, "Dump of %ld bytes of data", n);
note (1);
for (j = 0; j < n; ++j)
{
fprintf (stdout, "%3d", the_data[j]);
if ((j % 20) == 19)
putc ('\n', stdout);
else
putc (' ', stdout);
}
putc ('\n', stdout);
}
}
void
proto_badboy (void)
{
printf ("Hello world.\n");
}
#if defined(__ALPHA) && defined(VMS) && !defined(NOCASTAWAY)
#include
#endif
BADBOY
castaway (unsigned char *dat)
{
#if defined(VAX) && !defined(NOCASTAWAY)
/* register save mask avoids bashing our callers locals */
((unsigned short *) dat)[0] = 0x0FFC;
#endif
#if defined(__ALPHA) && defined(VMS) && !defined(NOCASTAWAY)
struct pdscdef *p, *b;
p = (struct pdscdef *) proto_badboy;
b = (struct pdscdef *) dat;
memcpy (b, p, sizeof (struct pdscdef));
b->pdsc$q_entry[1] = 0;
b->pdsc$q_entry[0] = (int) &dat[sizeof (struct pdscdef)];
#endif
#if (defined(_IBMR2) || defined(_POWER)) && !defined(NOCASTAWAY)
struct fdesc
{
void *fcn_addr;
void *toc;
void *linkage;
} *p, *b;
p = (struct fdesc *) proto_badboy;
b = (struct fdesc *) dat;
memcpy (b, p, sizeof (struct fdesc));
b->fcn_addr = (void *) &dat[sizeof (struct fdesc)];
#endif
#if defined(__hpux) && defined(__hppa) && !defined(NOCASTAWAY)
struct fdesc
{
void *fcn_addr;
void *toc;
} *p, *b;
p = (struct fdesc *) proto_badboy;
b = (struct fdesc *) dat;
memcpy (b, p, sizeof (struct fdesc));
b->fcn_addr = (void *) &dat[sizeof (struct fdesc)];
#endif
return ((BADBOY) dat);
}
void
compute_badboy (void)
{
long n;
n = (nbytes < 0) ? -nbytes : nbytes;
if (incptr == 0)
{
compute_badboy_1 (n);
badboy = castaway (the_data);
}
else if ((next_offset == 0) || (next_offset > ((n * 90) / 100)))
{
compute_badboy_1 (n);
offset = 0;
next_offset = offset + incptr;
badboy = castaway (the_data);
}
else
{
offset = next_offset;
next_offset = offset + incptr;
badboy = castaway (&the_data[offset]);
}
}
/* maybe add this code before invoking badboy. But it didn't seem
to be needed when using +1000.
FlushInstructionCache(GetCurrentProcess(),
the_data,(nbytes < 0) ? - nbytes : nbytes);
*/
void
try_one_crash (void)
{
if (nbytes > 0)
(*badboy) ();
else if (nbytes == 0)
while (1);
}
int
main (int argc, char **argv)
{
long nsubs, hrs, mns, scs, tflag, j, m;
note_buffer = (char *) malloc (NOTE_BUFFER_LEN);
notes = note_buffer;
if ((argc == 7) && (strcmp (argv[6], subprocess_ind) == 0))
{
sprintf (note_buffer, "Subprocess %s: ", argv[4]);
subprocess_flag = 1;
notes = note_buffer + strlen (note_buffer);
verbose_level = atol (argv[5]);
sprintf (notes, "starting");
open_record ();
note (3);
record_note ();
old_main (4, argv);
}
else if (argc == 4)
{
open_record ();
old_main (4, argv);
}
else if ((argc == 6) && ((strlen (argv[4]) == 0) ||
(strcmp (argv[4], ".") == 0)))
{
verbose_level = atol (argv[5]);
open_record ();
old_main (4, argv);
}
else if ((argc == 5) || (argc == 6))
{
open_record ();
if (argc == 6)
verbose_level = atol (argv[5]);
copyright_note (1);
if (argc < 7)
m = argc;
else
m = 6;
strcpy (notes, "crashme");
for (j = 1; j < m; ++j)
{
strcat (notes, " ");
strcat (notes, argv[j]);
}
note (1);
record_note ();
if (strchr (argv[4], ':'))
{
sscanf (argv[4], "%ld:%ld:%ld", &hrs, &mns, &scs);
tflag = 1;
nsubs = (((hrs * 60) + mns) * 60) + scs;
sprintf (notes,
"Subprocess run for %ld seconds (%ld %02ld:%02ld:%02ld)",
nsubs, hrs / 24, hrs % 24, mns, scs);
}
else
{
tflag = 0;
nsubs = atol (argv[4]);
sprintf (notes, "Creating %ld crashme subprocesses", nsubs);
}
note (1);
prng_setup (0);
record_note ();
vfork_flag = 1;
vfork_main (tflag, nsubs, argv[0], argv[1], atol (argv[2]), argv[3]);
}
else
{
open_record ();
sprintf (notes,
"crashme [+][.inc] [nsub] [verbose]");
note (0);
}
close_record ();
return (EXIT_SUCCESS);
}
void
copyright_note1 (long n)
{
sprintf (notes, "Crashme: (c) Copyright 1990-2012 George J. Carrette");
note (n);
sprintf (notes, "Version: %s", crashme_version);
note (n);
sprintf (notes, "From http://alum.mit.edu/www/gjc/crashme.html");
note (n);
#ifdef PRNG_MT
sprintf (notes,
"With http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html");
note (n);
#endif
}
void
copyright_note (long n)
{
if (subprocess_flag == 0)
copyright_note1 (n);
}
void
prng_setup (long nseed)
{
char *prng_name, *tmp;
prng_name = "";
if ((tmp = getenv ("CRASHPRNG")) && (strcmp (tmp, "") != 0))
prng_name = tmp;
if (strcmp (prng_name, "RAND") == 0)
prng_type = PRNG_TYPE_RAND;
else if (strcmp (prng_name, "MT") == 0)
prng_type = PRNG_TYPE_MT;
else if (strcmp (prng_name, "VNSQ") == 0)
prng_type = PRNG_TYPE_VNSQ;
else
prng_type = PRNG_DEFAULT;
switch (prng_type)
{
case PRNG_TYPE_MT:
#ifdef PRNG_MT
sprintf (notes, "CRASHPRNG %s %d Mersenne twister.", prng_name,
prng_type);
init_genrand (nseed);
#endif
break;
case PRNG_TYPE_RAND:
sprintf (notes, "CRASHPRNG %s %d C runtime library rand.", prng_name,
prng_type);
srand (nseed);
break;
case PRNG_TYPE_VNSQ:
sprintf (notes, "CRASHPRNG %s %d VN middle square.", prng_name,
prng_type);
init_vnsq (nseed);
break;
default:
sprintf (notes, "CRASHPRNG %s %d UNKNOWN", prng_name, prng_type);
break;
}
note ((subprocess_flag == 0) ? 1 : 3);
record_note ();
}
void
old_main (int argc, char **argv)
{
char *ptr;
copyright_note (3);
nbytes = atol (argv[1]);
if ((ptr = strchr (argv[1], '.')) != NULL)
incptr = atol (&ptr[1]);
if (argv[1][0] == '+')
malloc_flag = 1;
nseed = atol (argv[2]);
ntrys = atol (argv[3]);
sprintf (notes, "crashme %s%ld.%ld %ld %ld",
(malloc_flag == 0) ? "" : "+", nbytes, incptr, nseed, ntrys);
note (3);
record_note ();
if (malloc_flag == 0)
{
the_data = bad_malloc ((nbytes < 0) ? -nbytes : nbytes);
badboy = castaway (the_data);
sprintf (notes, "Badboy at %ld. 0x%lX", (long) badboy, (long) badboy);
note (3);
}
prng_setup (nseed);
#ifdef WIN32
SetErrorMode (SEM_FAILCRITICALERRORS |
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
#endif
badboy_loop ();
}
#ifdef WIN32
char *
likely_exception_string (DWORD value)
{
switch (value)
{
case EXCEPTION_ACCESS_VIOLATION:
return("EXCEPTION_ACCESS_VIOLATION");
case EXCEPTION_DATATYPE_MISALIGNMENT:
return("EXCEPTION_DATATYPE_MISALIGNMENT");
case EXCEPTION_BREAKPOINT:
return("EXCEPTION_BREAKPOINT");
case EXCEPTION_SINGLE_STEP:
return("EXCEPTION_SINGLE_STEP");
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
return("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
case EXCEPTION_FLT_DENORMAL_OPERAND:
return("EXCEPTION_FLT_DENORMAL_OPERAND");
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
return("EXCEPTION_FLT_DIVIDE_BY_ZERO");
case EXCEPTION_FLT_INEXACT_RESULT:
return("EXCEPTION_FLT_INEXACT_RESULT");
case EXCEPTION_FLT_INVALID_OPERATION:
return("EXCEPTION_FLT_INVALID_OPERATION");
case EXCEPTION_FLT_OVERFLOW:
return("EXCEPTION_FLT_OVERFLOW");
case EXCEPTION_FLT_STACK_CHECK:
return("EXCEPTION_FLT_STACK_CHECK");
case EXCEPTION_FLT_UNDERFLOW:
return("EXCEPTION_FLT_UNDERFLOW");
case EXCEPTION_INT_DIVIDE_BY_ZERO:
return("EXCEPTION_INT_DIVIDE_BY_ZERO");
case EXCEPTION_INT_OVERFLOW:
return("EXCEPTION_INT_OVERFLOW");
case EXCEPTION_PRIV_INSTRUCTION:
return("EXCEPTION_PRIV_INSTRUCTION");
case EXCEPTION_IN_PAGE_ERROR:
return("EXCEPTION_IN_PAGE_ERROR");
case EXCEPTION_ILLEGAL_INSTRUCTION:
return("EXCEPTION_ILLEGAL_INSTRUCTION");
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
return("EXCEPTION_NONCONTINUABLE_EXCEPTION");
case EXCEPTION_STACK_OVERFLOW:
return("EXCEPTION_STACK_OVERFLOW");
case EXCEPTION_INVALID_DISPOSITION:
return("EXCEPTION_INVALID_DISPOSITION");
case EXCEPTION_GUARD_PAGE:
return("EXCEPTION_GUARD_PAGE");
case EXCEPTION_INVALID_HANDLE:
return("EXCEPTION_INVALID_HANDLE");
case CONTROL_C_EXIT:
return("CONTROL_C_EXIT");
default:
return("");
}
}
DWORD
exception_filter (DWORD value)
{
int sev, cus, res, fac, cod;
char *str;
sev = 3 & (value >> 30);
cus = 1 & (value >> 29);
res = 1 & (value >> 28);
fac = 07777 & (value >> 16);
cod = 0xFFFF & value;
str = likely_exception_string(value);
sprintf (notes, "sev(%d)cus(%d)res(%d)fac(%d)code(%d) %s",
sev, cus, res, fac, cod, str);
note (5);
return (EXCEPTION_EXECUTE_HANDLER);
}
#endif
void
badboy_loop (void)
{
int i;
for (i = 0; i < ntrys; ++i)
{
compute_badboy ();
if (offset)
sprintf (notes, "try %d, offset %ld", i, offset);
else if (malloc_flag == 1)
sprintf (notes, "try %d, Badboy at %ld. 0x%lX", i, (long) badboy,
(long) badboy);
else
sprintf (notes, "try %d", i);
note (5);
#ifdef WIN32
__try
{
try_one_crash ();
sprintf (notes, "didn't barf!");
note (5);
}
__except (exception_filter (GetExceptionCode ()))
{
}
#else
if (setjmp (again_buff) == 3)
{
sprintf (notes, "Barfed");
note (5);
}
else
{
set_up_signals ();
alarm (10);
try_one_crash ();
sprintf (notes, "didn't barf!");
note (5);
}
#endif
}
}
struct status_list
{
long status;
long count;
struct status_list *next;
};
struct status_list *slist = NULL;
void
record_status (long n)
{
struct status_list *l;
for (l = slist; l != NULL; l = l->next)
if (n == l->status)
{
++l->count;
return;
}
l = (struct status_list *) malloc (sizeof (struct status_list));
l->count = 1;
l->status = n;
l->next = slist;
slist = l;
}
void
summarize_status (void)
{
struct status_list *l;
char *status_str = "";
int n = 0;
sprintf (notes, "child_kill_count %ld", child_kill_count);
note (2);
sprintf (notes, "exit status ... number of cases");
note (2);
for (l = slist; l != NULL; l = l->next)
{
#ifdef WIN32
status_str = likely_exception_string (l->status);
#endif
sprintf (notes, "%11ld ... %5ld %s", (long) l->status, (long) l->count, status_str);
note (2);
++n;
}
strcpy (notes, "");
note (2);
sprintf (notes, "Number of distinct cases = %d", n);
note (2);
}
#ifndef WIN32
long monitor_pid = 0;
long monitor_period = 5;
long monitor_limit = 6; /* 30 second limit on a subprocess */
long monitor_count = 0;
long monitor_active = 0;
void
monitor_fcn (int sig)
{
long status;
my_signal (SIGALRM, monitor_fcn);
alarm (monitor_period);
if (monitor_active)
{
++monitor_count;
if (monitor_count >= monitor_limit)
{
sprintf (notes, "time limit reached on pid %ld 0x%lX. using kill.",
(long) monitor_pid, (long) monitor_pid);
note (3);
status = kill (monitor_pid, SIGKILL);
if (status < 0)
{
sprintf (notes, "failed to kill process");
note (3);
}
else
{
++child_kill_count;
}
monitor_active = 0;
}
}
}
void
vfork_main (long tflag, long nsubs, char *cmd, char *nb, long sr, char *nt)
{
long j, pid, n, seq, total_time, dys, hrs, mns, scs;
int status;
long pstatus;
char arg2[20], arg4[20], arg5[20];
time_t before_time, after_time;
if (tflag == 1)
{
seq = 1;
n = 100000000;
}
else if (nsubs < 0)
{
n = -nsubs;
seq = 1;
}
else
{
n = nsubs;
seq = 0;
}
if (seq == 1)
{
my_signal (SIGALRM, monitor_fcn);
alarm (monitor_period);
}
time (&before_time);
sprintf (arg5, "%ld", verbose_level);
for (j = 0; j < n; ++j)
{
sprintf (arg2, "%ld", sr + j);
sprintf (arg4, "%ld", j + 1);
#ifdef VMS
pstatus = vfork ();
#else
pstatus = fork ();
#endif
if (pstatus == 0)
{
status =
execlp (cmd, cmd, nb, arg2, nt, arg4, arg5, subprocess_ind, NULL);
if (status == -1)
{
perror (cmd);
exit (1);
}
}
else if (pstatus < 0)
perror ("fork");
else
{
sprintf (notes, "pid = %ld 0x%lX (subprocess %ld)", pstatus,
pstatus, j + 1);
note (3);
if (seq == 1)
{
monitor_pid = pstatus;
monitor_count = 0;
monitor_active = 1;
while ((pid = wait (&status)) > 0)
{
monitor_active = 0;
sprintf (notes, "pid %ld 0x%lX exited with status %d",
(long) pid, (long) pid, status);
note (3);
record_status (status);
record_note ();
}}
if (tflag == 1)
{
time (&after_time);
total_time = after_time - before_time;
if (total_time >= nsubs)
{
sprintf (notes, "Time limit reached after run %ld", j + 1);
note (2);
record_note ();
break;
}
}
}
}
if (seq == 0)
while ((pid = wait (&status)) > 0)
{
sprintf (notes, "pid %ld 0x%lX exited with status %d", (long) pid,
(long) pid, status);
note (3);
record_status (status);
record_note ();
}
time (&after_time);
total_time = after_time - before_time;
scs = total_time;
mns = scs / 60;
hrs = mns / 60;
dys = hrs / 24;
scs = scs % 60;
mns = mns % 60;
hrs = hrs % 24;
sprintf (notes,
"Test complete, total real time: %ld seconds (%ld %02ld:%02ld:%02ld)",
(long) total_time, (long) dys, (long) hrs, (long) mns, (long) scs);
note (1);
summarize_status ();
}
#else
char *
find_exe_self (char *cmd)
/* function grabbed from SIOD */
{
DWORD retsize;
char exe_self[512];
retsize = SearchPath (NULL, cmd, ".EXE", sizeof (exe_self), exe_self, NULL);
if (retsize > 0)
return (_strdup (exe_self));
else
return (cmd);
}
void
chk_CloseHandle (HANDLE h)
{
DWORD err;
if (CloseHandle (h) == FALSE)
{
err = GetLastError ();
sprintf (notes, "err %d trying to close handle.", err);
note (3);
}
}
int maxticks = 100; /* tenths of a second before forced termination
of the subprocess */
void
vfork_main (long tflag, long nsubs, char *cmd, char *nb, long sr, char *nt)
{
long j, n, seq, total_time, dys, hrs, mns, scs;
char arg0[512];
char arg2[20], arg4[20], arg5[20];
time_t before_time, after_time;
char cmdbuf[1024];
int nticks;
PROCESS_INFORMATION pinfo;
STARTUPINFO sinfo;
DWORD exit_code, err;
if (tflag == 1)
{
seq = 1;
n = 100000000;
}
else if (nsubs < 0)
{
n = -nsubs;
seq = 1;
}
else
{
n = nsubs;
seq = 0;
}
/* tflag says this is a timed run. So nsub is the time in seconds.
seq says to run in sequence, not created nsub processes all
at once. */
if (seq == 0)
{
printf ("Not implemented. Use [-nsub] or [HH:MM:SS] instead.\n");
return;
}
time (&before_time);
sprintf (arg5, "%d", verbose_level);
for (j = 0; j < n; ++j)
{
sprintf (arg0, "%s", find_exe_self (cmd));
sprintf (arg2, "%d", sr + j);
sprintf (arg4, "%d", j + 1);
sprintf (cmdbuf, "\"%s\" %s %s %s %s %s %s",
cmd, nb, arg2, nt, arg4, arg5, subprocess_ind);
memset (&sinfo, 0, sizeof (sinfo));
memset (&pinfo, 0, sizeof (pinfo));
sinfo.cb = sizeof (sinfo);
if (CreateProcess
(arg0, cmdbuf, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo,
&pinfo) == FALSE)
{
err = GetLastError ();
sprintf (notes, "err %d trying to create process", err);
note (1);
record_note ();
continue;
}
sprintf (notes, "pid = %d 0x%X (subprocess %d)",
pinfo.dwProcessId, pinfo.dwProcessId, j + 1);
note (3);
record_note ();
nticks = 0;
while (1)
{
if (GetExitCodeProcess (pinfo.hProcess, &exit_code) == TRUE)
{
if (exit_code == STILL_ACTIVE)
{
if (nticks == maxticks)
{
sprintf (notes,
"time limit reached on pid %d 0x%X. using kill.",
pinfo.dwProcessId, pinfo.dwProcessId);
note (3);
record_note ();
if (TerminateProcess (pinfo.hProcess,
APPLICATION_ERROR_MASK |
ERROR_SEVERITY_ERROR |
1) == FALSE)
{
err = GetLastError ();
sprintf (notes,
"err %d trying to terminate process.",
err);
note (3);
record_note ();
chk_CloseHandle (pinfo.hProcess);
chk_CloseHandle (pinfo.hThread);
break;
}
else
{
++child_kill_count;
}
++nticks;
}
else
{
++nticks;
Sleep (100);
}
}
else
{
sprintf (notes, "pid %d 0x%X exited with status %d",
pinfo.dwProcessId, pinfo.dwProcessId, exit_code);
note (3);
record_status (exit_code);
chk_CloseHandle (pinfo.hProcess);
chk_CloseHandle (pinfo.hThread);
record_note ();
break;
}
}
else
{
err = GetLastError ();
sprintf (notes, "err %d on GetExitCodeProcess.", err);
note (3);
chk_CloseHandle (pinfo.hProcess);
chk_CloseHandle (pinfo.hThread);
record_note ();
break;
}
}
if (tflag == 1)
{
time (&after_time);
total_time = (long) (after_time - before_time);
if (total_time >= nsubs)
{
sprintf (notes, "Time limit reached after run %d", j + 1);
note (2);
record_note ();
break;
}
}
}
time (&after_time);
total_time = (long) (after_time - before_time);
scs = total_time;
mns = scs / 60;
hrs = mns / 60;
dys = hrs / 24;
scs = scs % 60;
mns = mns % 60;
hrs = hrs % 24;
sprintf (notes,
"Test complete, total real time: %d seconds (%d %02d:%02d:%02d)",
total_time, dys, hrs, mns, scs);
note (1);
summarize_status ();
}
#endif
crashme-2.8.5/mt19937ar.h 0000644 0001750 0001750 00000000427 12317647533 013007 0 ustar gjc gjc void init_genrand(unsigned long s);
void init_by_array(unsigned long init_key[], int key_length);
unsigned long genrand_int32(void);
long genrand_int31(void);
double genrand_real1(void);
double genrand_real2(void);
double genrand_real3(void);
double genrand_res53(void);
crashme-2.8.5/vnsq.c 0000664 0001750 0001750 00000001460 12370416647 012410 0 ustar gjc gjc /* -*- Mode: C; indent-tabs-mode: nil -*- */
#include
#include
#include
#include "vnsq.h"
unsigned long vnsq_value = 137;
void
init_vnsq (unsigned long seed)
{
vnsq_value = seed;
}
unsigned long
vnsq_int32 (void)
{
unsigned long nextn;
int nextlen;
int excess;
int left_excess;
int right_excess;
char decimalrep[50];
char *nextp;
nextn = vnsq_value * vnsq_value;
sprintf (decimalrep, "%lu", nextn);
nextlen = (int) (strlen (decimalrep));
excess = nextlen - 6;
if (excess > 0)
{
right_excess = excess / 2;
left_excess = right_excess + (excess % 2);
nextp = &decimalrep[left_excess];
decimalrep[nextlen - right_excess] = 0;
vnsq_value = atol (nextp);
}
else
{
vnsq_value = nextn;
}
return (nextn);
}
crashme-2.8.5/crashme.html 0000644 0001750 0001750 00000032361 12336654103 013560 0 ustar gjc gjc
CRASHME: Random input testing.
CRASHME: Random input testing
Copyright 1996-2014 by George J. Carrette. All rights Reserved.
See the source crashme.c for reports of system crashes.
Software available:
Acknowledgements.
Many people have provided suggestions and comments and
feedback. Some in private email and some as published on the comp.arch
newsgroups. But as the author of this gross hack I take full
responsibility for any errors in the information presented.
A bit of background on crashme. It is a tool for testing the
robustness of an operating environment using a technique of "Random
Input" response analysis. This I first saw formally proposed in the
book Cybernetics by Norbert Wiener, but which any parent who has
observed his children playing and learning would be well disposed to
describe in detail.
- The operating environment under consideration is the user-mode process.
- The Random Input is provided by the execution of a sequence of pseudo-random data as an instruction stream.
- The response analysis is to catch and record machine and software
generated exceptions/errors/signals and to retry using new random data
in both the current user-mode process and in newly created
subprocesses.
Notes for release 2.2 of Crashme. 9-MAY-1994 GJC@ALUM.MIT.EDU
Added the X.Y syntax for the NBYTES argument. This may run faster,
doing more tests per second. A reasonable value for Y would be
the number of bytes in a machine instruction.
Many people have suggested that the output of previous versions was
far too verbose, and that that was not only annoying but also
effectively slowing down the program. Therefore there is a new argument
available after the subprocess control argument, which is a verboseness
level from 0 to 5. Using a level of 2 will print out only summary
information about the runs. e.g.
$ crashme +2000 666 50 00:30:00 2
Crashme: (c) Copyright 1990, 1991 George J. Carrette
Version: 1.7 25-SEP-1991
Subprocess run for 1800 seconds (0 00:30:00)
Test complete, total real time: 1801 seconds (0 00:30:01)
exit status ... number of cases
1100 ... 2
3522652 ... 4
1036 ... 1
1084 ... 7
1108 ... 19
1 ... 432
12 ... 137
The table of exit status codes and frequencies is a new interesting
aspect of the test. This test was run on a VMS system, so that we have
a normal process exit 432 times, access violation 137 times,
and reserved operand fault 19 times, etc. As the number of tries goes
up (50 in this case) we would expect that the number of normal process
exits to go down.
If you define an environment variable (or vms logical name)
called CRASHLOG then each subprocess will append to a file the
arguments it was given. In that way you can recover what instance
possibly caused a crash, but remember that without frequent disk fsync
operations most Unix systems will leave a CRASHLOG that is out of
date by a few minutes or more.
Here is some output supplied by nik@infonode.ingr.com on one of his machines.
Processor : Intergraph Clipper C300 RISC processor
16Mb memory + 4k I cache and 4K D cache
Operating System: CLIX Version c.5.3.2
derived from AT&T SVR 3.1 with BSD enhancements.
Crashme: (c) Copyright 1990, 1991 George J. Carrette
Version: 1.7 25-SEP-1991
Subprocess run for 9000 seconds (0 02:30:00)
Test complete, total real time: 9004 seconds (0 02:30:04)
exit status ... number of cases
136 ... 1
24576 ... 1
14 ... 1
138 ... 11
135 ... 27
140 ... 26
132 ... 430
139 ... 18
12800 ... 567
The status values here could be decoded by reading the
documentation for the "wait" system procedure, and looking up the
correct part of the value in the sys_errlist[] array. That is left as
an exersize for the reader.
To compile, some systems may need #include <sys/types.h>.
Also, note the conditionalized code in bad_malloc. If your system
only gets the signal "segmentation violation" then you may need
to consider conditionalizations along this line.
However, on a machine with a segmented address space, that has
"instructions" in one segment and "data" in another, it is highly
unlikely that the code for setting up and invoking the "void
(*badboy)()" will have any interesting effect. Nothing other than an
easily handled SIGSEGV will result in the inner testing loop.
Some PDP-11 systems would be examples of this situation (different
I and D space).
---MACHINE O/S SPECIFIC NOTES---
MACHINE:: DEC C (OPENVMS ALPHA AXP):
$ CC/PREFIX=ALL/NOOPTIMIZE CRASHME
$ LINK CRASHME
New for version 2.2 code has been added to hackishly manipulate
the Procedure Descriptor data format. It seems be executing random
instructions like we would want.
#if defined(__ALPHA) && defined(VMS) && !defined(NOCASTAWAY)
Without this hack crashme on this platform has very little chance
of causing anything other than a SIGBUS bus error.
Perhaps a smart "learning" mode of random-data creation could
achieve the same ends, maximizing some measurement of punishment.
Genetic programming might be useful.
Test I've tried:
$crashme +1000.48 0 100 03:00:00 2
MACHINE:: Windows NT:
The only files needed are crashme.c,makefile.wnt, and make.bat. cd
into the directory containing the files and you can make two versions.
crashme and crashmep (posix).
>make
In WIN32 subsystem the subprocess-all-at-once mode has not been
implemented, but the sequential (-nsub) and timed modes have been
implemented.
In posix subsystem you must use the full name of the file in the
command if you want to generate subprocesses.
>crashmep.exe .....
On an 486DX2-66 machine the following caused a totally
wedged up machine in the Windows NT final release. (Build 511).
This was built in WIN32 mode with debugging on.
>crashme +1000 666 50 12:00:00 3
In the posix subsystem the more verbose modes were not ever observed
to go through more than 2 setjmp/longjmp cycles on a given random
number seed. In the WIN32 subsystem there was a greater variety of
fault conditions.
The above crash took place after about 6 hours of running. Final
subprocess arguments were +1000 24131 50, and we verified twice that
invoking the following crashed the OS within seconds.
>crashme +1000 24131 50
I have always been concerned that the more complex the unprotected
data in the user address space the more likely it is for a program
being developed to generate inscrutable errors that an "application
developer" level of person will be unable to understand. And worse,
will end up spinning wheels for large amounts of time, thereby
delaying projects and risking deadline failures, and even worse,
forcing management to bring in super-experienced (and limited
availability) people into a project in order to get it going again.
The WINDOWS NT client-server model is one way around this problem.
Having a subsystem in a different address space is one way to protect
complex data manipulated through an API. However, as page 127 of
"Inside Windows NT" there are some optimizations that make an unspoken
trade-off between the robustness afforded by a protected seperate
address space and efficiency of implementation on an API.
Robustness and 'scrutability of failure situations' vs efficiency.
MACHINE:: OS/2
It has been reported that this runs when compiled gcc crashme.c -o
crashme.exe In order to disable the dialog boxes reporting abnormal
process termination, add this to CONFIG.SYS: AUTOFAIL=YES. Or the
following code to main:
DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
Another person says that Emx is the only c compiler under OS/2 that
supports fork.
Survey of Procedure Descriptor Usage. The emphasis here is on
currently shipping products. The program pddet.c included
with the distribution can be used to determine some of this
information. Note that in some environments, e.g. Microsoft C++ 4.0
the results of PDDET will be different depending on the compilation
modes chosen: debug verses release.
Architecture |D| Desc | Env | Reg | Apos | Atyp | Rpos | Rtyp |
------------------------------------------------------------------
VAX |2| No | No | Yes | No | No | No | No |
ALPHA, OPENVMS |3| Yes | Yes | Yes | Yes | Opt | Yes | Opt |
ALPHA, WNT | | No | | | | | | |
ALPHA, OSF/1 | | No | | | | | | |
RS/6000, AIX |2| Yes | Yes | No | No | No | No | No |
PowerPC, |2| Yes | Yes | No | No | No | No | No |
MIPS, Unix | | | | | | | | |
MIPS, WNT | | | | | | | | |
Intel, WNT | | | | | | | | |
Sparc, SUNOS | | No | | | | | | |
PA-RISC, HPUX |2| Yes | | | | | | |
------------------------------------------------------------------
Legend:
D ... level of detailed information I have available
1 = Verbal description or suspect from pddet.c
2 = exact structure details including code for CRASHME.C
or obvious what it is from pddet.c
3 = crashme uses manufacturers include files for descriptors.
Desc ... Uses descriptors
Env ... has pointer to non-static environment
Reg ... describes registers used
Apos ... describes argument positions (stack, registers) or number.
Atyp ... describes argument types
Rpos ... describes return value position.
Rtyp ... describes return value types
Layout of Descriptors. Sizes in bytes.
ALPHA OPENVMS:
[FLAGS&KIND] 2
[REG-SAVE] 2
[REG-FOR-RETPC] 1
[REG-FOR-RETVAL] 1
[SIGNATURE-OFFSET] 2
[START-PC] 8
[Other stuff ...] from 8 to 32 bytes worth.
AIX
actually points to a 3 word struct with:
- the actual function address
- Table Of Contents (r2) register value
- Environment (r11) pointer (for nested functions)
POWERPC
[PROGRAM-COUNTER]
[TABLE-OF-CONTENTS]
[EXCEPTION-INFO]
[Editorial comment taken from comp.arch:] Not to sound picky about
this, but this is not really part of the POWER/PowerPC architecture.
There is no special support for this in the hardware, it is just the
scheme the software designers came up with in order to support shared
libraries. Other schemes would be possible. [GJC comment] Pretty
much true for every architecture.
PA-RISC HPUX.
The pddet.c program was used, and suggested descriptors of 8
bytes long. The -examine 8 argument showed what appeared to
be a 4-byte starting PC followed by a table of contents.
Note: If somebody knows what /usr/include/sys/*.h file to use
for this, please let me know.
Notes for release 2.6 of Crashme. 13-JUL-2008 GJC.
CRASHPRNG is a new environment variable letting you change the
pseudorandom number generator used.
CRASHPRNG | description |
RAND | C runtime library rand |
MT (default) |
Mersenne twister coded by Takuji Nishimura and Makoto Matsumoto. |
VNSQ |
A variation of the middle square method |
crashme-2.8.5/crashme.man 0000644 0001750 0001750 00000010116 12370420304 013351 0 ustar gjc gjc .TH CRASHME 1
.SH NAME
crashme \- test operating environment software robustness
.SH SYNOPSIS
.B crashme
[NBYTES] [SRAND] [NTRYS] [NSUB] [VERBOSE]
.SH DESCRIPTION
.I crashme
is a very simple program that tests the operating environment's
robustness by invoking random data as if it were a procedure.
The standard signals are caught and handled with a setjmp back
to a loop which will try again to produce a fault by executing
random data. Some people call this stress testing.
.RE
.SS COMMAND LINE OPTIONS
.TP 8
.BI [NBYTES]
The
.I [NBYTES]
should be an integer, specifying the size of the random data string
in bytes. If given negative then the bytes are printed instead of
being executed. If given with an explicit plus sign then the
storage for the bytes is freshly malloc'ed each time. This can have an
effect on machines with separate I and D cache mechanisms. The argument
can also have a dot in it, X.Y, in which case Y is a increment for
a pointer into the random data. The buffer is recalculated only when
the pointer gets near the end of the data.
The are two magic values for
.I [NBYTES]
:
A value of 81920 avoids malloc and returns a pointer to
static data. This makes the operation of crashme more
repeatable on architectures where malloc is designed to
return unpredictable locations. A value of 1025 avoids a call
that sets the protection of the data to READ+WRITE+EXEC.
.TP
.BI [SRAND]
The
.I [SRAND]
is an input seed to the random number generator, passed to srand.
.TP
.BI [NTRIES]
The
.I [NTRIES]
is how many times to loop before exiting normally from the program.
.TP
.BI [NSUB]
The
.I [NSUB]
is optional, the number of vfork subprocesses running all at once.
If negative run one after another. If given as a
time hrs:mns:scs (hours, minutes, seconds) then
one subprocess will be run to completion, followed by another, until
the time limit has been reached. If this argument is given as the empty
string or . then it is ignored.
When in sequential-subprocess mode there is a 30 second time limit on
each subprocess. This is to allow the instruction-set-space random
walk to continue when a process bashes itself into an infinite loop.
For example, the ntrys can be bashed to a very large number with
nbytes bashed to zero. (10 second limit on Windows NT).
The SRAND argument is incremented by one for each subprocess.
.TP
.BI [VERBOSE]
The
.I [VERBOSE]
arg is optional. 0 is the least verbose, 5 the most.
.SS ENVIRONMENT VARIABLES
.TP 8
.BI CRASHLOG
The
.I CRASHLOG
is the name of the file which the parent process opens in write mode
and all child processes open in append mode. There is frequent flushing
of the file but no locking, so the output may be interleaved. If the
operating system crashes then this file might provide a short-cut
to a more resent random number seed sequence to allow for quicker
finding of the special case that caused the crash.
.TP
.BI CRASHPRNG
The
.I CRASHPRNG
can be set to RAND to use the system-provided rand function, or MT
to use the Mersenne twister (default) as coded by
Takuji Nishimura and Makoto Matsumoto, or VNSQ to use the author's
kludge interpretation of Von Neumann's middle-square method.
.SH EXAMPLE
This is a suggested test, to run it for a least an hour.
crashme +2000 666 100 1:00:00
.SH FILES
crashme.c
.PD
.SH DIAGNOSTICS
When a signal is caught the number and nature of the signal is indicated.
Setting the environment variable CRASHLOG will cause each subprocess to
record the arguments it was given.
.SH BUGS
Not all signals are caught, and the state of the user program/process
environment can be sufficiently damaged such that the program terminates
before going through all [NTRIES] operations.
If the architecture uses some kind of procedure descriptor but no
special code has been not been added to castaway() in crashme.c
then the stress test will not be as potent as it would otherwise be.
Beware: This program can crash your computer if the
operating system or hardware of same is buggy. User data may be lost.
.SH AUTHOR
George J Carrette. GJC\@alum.mit.edu
http://people.delphiforums.com/gjc/crashme.html
http://crashme.codeplex.com/
.SH VERSION
2.8.5 6-AUG-2014
crashme-2.8.5/vnsq.h 0000644 0001750 0001750 00000000106 12343055151 012374 0 ustar gjc gjc void init_vnsq (unsigned long seed);
unsigned long vnsq_int32 (void);