mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-01 10:47:38 +01:00
04c77cced4
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 ]
126 lines
2.3 KiB
C
126 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;
|
|
}
|
|
|