1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-06-17 07:21:44 +02:00
libunwind-eh_elf/tests/crasher.c
Konstantin Belousov 04c77cced4 Fix for test suite build in the separate directory.
Avoid manually coding the rule to build crasher, instead fuddle
the compiler so that even -O2 optimization does not eliminate call
to b().

First, put calls to both a() and b() in the b() into non-tail-recursive
position. Second, as recommended in gcc manual, use asm volatile("");
to prevent further prevent inlining, besides attribute((noinline).
And third, call b() by alias, which current gcc optimizer cannot see
through.

Also, do not dereference NULL in a, and mark the memory access as volatile.
[ Minor portability improvements: asharma@fb.com ]
2012-08-11 22:02:55 -07:00

127 lines
2.3 KiB
C

/* This program should crash and produce coredump */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef __FreeBSD__
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#endif
#if defined(__linux__)
void write_maps(char *fname)
{
char buf[512], path[128];
char exec;
uintmax_t addr;
FILE *maps = fopen("/proc/self/maps", "r");
FILE *out = fopen(fname, "w");
if (!maps || !out)
exit(EXIT_FAILURE);
while (fgets(buf, sizeof(buf), maps))
{
if (sscanf(buf, "%jx-%*jx %*c%*c%c%*c %*x %*s %*d /%126[^\n]", &addr, &exec, path+1) != 3)
continue;
if (exec != 'x')
continue;
path[0] = '/';
fprintf(out, "0x%jx:%s ", addr, path);
}
fprintf(out, "\n");
fclose(out);
fclose(maps);
}
#elif defined(__FreeBSD__)
void
write_maps(char *fname)
{
FILE *out;
char *buf, *bp, *eb;
struct kinfo_vmentry *kv;
int mib[4], error;
size_t len;
out = fopen(fname, "w");
if (out == NULL)
exit(EXIT_FAILURE);
len = 0;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_VMMAP;
mib[3] = getpid();
error = sysctl(mib, 4, NULL, &len, NULL, 0);
if (error == -1)
exit(EXIT_FAILURE);
len = len * 4 / 3;
buf = malloc(len);
if (buf == NULL)
exit(EXIT_FAILURE);
error = sysctl(mib, 4, buf, &len, NULL, 0);
if (error == -1)
exit(EXIT_FAILURE);
for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) {
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
if (kv->kve_type == KVME_TYPE_VNODE &&
(kv->kve_protection & KVME_PROT_EXEC) != 0) {
fprintf(out, "0x%jx:%s ", kv->kve_start, kv->kve_path);
}
}
fprintf(out, "\n");
fclose(out);
free(buf);
}
#else
#error Port me
#endif
#ifdef __GNUC__
int a(void) __attribute__((noinline));
int b(int x) __attribute__((noinline));
int c(int x) __attribute__((noinline, alias("b")));
#define compiler_barrier() asm volatile("");
#else
int a(void);
int b(int x);
int c(int x);
#define compiler_barrier()
#endif
int a(void)
{
*(volatile int *)32 = 1;
return 1;
}
int b(int x)
{
int r;
compiler_barrier();
if (x)
r = a();
else
r = c(1);
return r + 1;
}
int
main (int argc, char **argv)
{
if (argc > 1)
write_maps(argv[1]);
b(0);
return 0;
}