28#include <sys/syscall.h>
29#elif defined(__darwin__)
31#elif defined(__FreeBSD__)
33# include <sys/sysctl.h>
34#elif defined(__NetBSD__)
36#elif defined(__DragonFly__)
38# include <sys/sysctl.h>
41extern unsigned int thr_self(
void);
42#elif defined(__HAIKU__)
43#include <FindDirectory.h>
49#define IR_PERF_JITDUMP_HEADER_MAGIC 0x4A695444
50#define IR_PERF_JITDUMP_HEADER_VERSION 1
52#define IR_PERF_JITDUMP_RECORD_LOAD 0
53#define IR_PERF_JITDUMP_RECORD_MOVE 1
54#define IR_PERF_JITDUMP_RECORD_DEBUG_INFO 2
55#define IR_PERF_JITDUMP_RECORD_CLOSE 3
56#define IR_PERF_JITDUMP_UNWINDING_UNFO 4
58#define ALIGN8(size) (((size) + 7) & ~7)
59#define PADDING8(size) (ALIGN8(size) - (size))
88static int jitdump_fd = -1;
91static uint64_t ir_perf_timestamp(
void)
95 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
108 snprintf(filename,
sizeof(filename),
"/tmp/jit-%d.dump", getpid());
109 if (!ir_perf_timestamp()) {
113#if defined(__linux__)
114 fd = open(
"/proc/self/exe", O_RDONLY);
115#elif defined(__NetBSD__)
116 fd = open(
"/proc/curproc/exe", O_RDONLY);
117#elif defined(__FreeBSD__) || defined(__DragonFly__)
119 size_t pathlen =
sizeof(path);
120 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
121 if (sysctl(mib, 4, path, &pathlen,
NULL, 0) == -1) {
124 fd = open(path, O_RDONLY);
126 fd = open(
"/proc/self/path/a.out", O_RDONLY);
127#elif defined(__HAIKU__)
129 if (find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH,
130 NULL, path,
sizeof(path)) != B_OK) {
134 fd = open(path, O_RDONLY);
142 ret = read(
fd, &elf_hdr,
sizeof(elf_hdr));
145 if (
ret !=
sizeof(elf_hdr) ||
146 elf_hdr.
emagic[0] != 0x7f ||
147 elf_hdr.
emagic[1] !=
'E' ||
148 elf_hdr.
emagic[2] !=
'L' ||
149 elf_hdr.
emagic[3] !=
'F') {
153 jitdump_fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666);
154 if (jitdump_fd < 0) {
158 jitdump_mem = mmap(
NULL,
159 sysconf(_SC_PAGESIZE),
161 MAP_PRIVATE, jitdump_fd, 0);
169 memset(&jit_hdr, 0,
sizeof(jit_hdr));
172 jit_hdr.
size =
sizeof(jit_hdr);
177 if (write(jitdump_fd, &jit_hdr,
sizeof(jit_hdr)) !=
sizeof(jit_hdr)) {
187 if (jitdump_fd >= 0) {
191 rec.
size =
sizeof(rec);
193 if (write(jitdump_fd, &rec,
sizeof(rec)) !=
sizeof(rec)) {
199 munmap(jitdump_mem, sysconf(_SC_PAGESIZE));
207 if (jitdump_fd >= 0) {
208 static uint64_t
id = 1;
211 uint32_t thread_id = 0;
212#if defined(__linux__)
213 thread_id = syscall(SYS_gettid);
214#elif defined(__darwin__)
215 uint64_t thread_id_u64;
216 pthread_threadid_np(
NULL, &thread_id_u64);
217 thread_id = (uint32_t) thread_id_u64;
218#elif defined(__FreeBSD__)
221 thread_id = (uint32_t)tid;
222#elif defined(__OpenBSD__)
223 thread_id = getthrid();
224#elif defined(__NetBSD__)
225 thread_id = _lwp_self();
226#elif defined(__DragonFly__)
227 thread_id = lwp_gettid();
229 thread_id = thr_self();
232 memset(&rec, 0,
sizeof(rec));
238 rec.
vma = (uint64_t)(uintptr_t)
start;
243 if (write(jitdump_fd, &rec,
sizeof(rec)) !=
sizeof(rec)
244 || write(jitdump_fd,
name,
len + 1) < 0
254 static FILE *fp =
NULL;
259 snprintf(filename,
sizeof(filename),
"/tmp/perf-%d.map", getpid());
260 fp =
fopen(filename,
"w");
fprintf($stream, string $format, mixed ... $values)
fopen(string $filename, string $mode, bool $use_include_path=false, $context=null)
memset(ptr, 0, type->size)
struct _ir_elf_header ir_elf_header
#define IR_PERF_JITDUMP_RECORD_LOAD
#define IR_PERF_JITDUMP_RECORD_CLOSE
int ir_perf_jitdump_register(const char *name, const void *start, size_t size)
struct _ir_perf_jitdump_record ir_perf_jitdump_record
#define IR_PERF_JITDUMP_HEADER_MAGIC
int ir_perf_jitdump_open(void)
struct _ir_perf_jitdump_load_record ir_perf_jitdump_load_record
int ir_perf_jitdump_close(void)
void ir_perf_map_register(const char *name, const void *start, size_t size)
#define IR_PERF_JITDUMP_HEADER_VERSION
ir_perf_jitdump_record hdr