mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-23 12:03:41 +01:00
ff0c6ccf6b
GCC is complaining about the `%*jx' match in sscanf() format string. Replace it with `%*x'; sscanf() will identically match an unsigned hexadecimal integer without the length modifier. crasher.c: In function 'write_maps': crasher.c:30:9: warning: use of assignment suppression and length modifier together in gnu_scanf format [-Wformat]
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-%*x %*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;
|
|
}
|
|
|