Created
August 18, 2012 01:09
-
-
Save chisophugis/3383753 to your computer and use it in GitHub Desktop.
uddt_fasttrap_sprint
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//usr/bin/true && clang $0 && exec ./a.out | |
//usr/bin/true && exit 1 | |
/* This program demonstrates how to dynamically create DTrace probes with | |
* fasttrap. It currently works on Mac x86(_64) but can be easily adapted | |
* to other platforms. | |
* | |
* Quickstart: | |
* To see it work, just execute it (that magic at the top will compile and | |
* run it). It will dynamically create a probe and print its probe | |
* specification. Then just trace it with `dtrace(1M)`. You'll see that it | |
* detects when the probe is enabled. | |
*/ | |
#include <stdio.h> | |
#include <fcntl.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/mman.h> | |
#include <err.h> | |
#include <sys/fasttrap.h> | |
#define PAGE_SIZE 4096 | |
void *get_rwx_page(void) | |
{ | |
void *ret; | |
if ((ret = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, | |
MAP_ANON|MAP_PRIVATE, -1, 0)) == NULL) { | |
err(1, "mmap"); | |
} | |
return ret; | |
} | |
int main() | |
{ | |
int fd; | |
void *execmem; | |
uint8_t *execmem_bytes; | |
if ((fd = open("/dev/fasttrap", O_RDWR)) < 0) { | |
err(1, "open"); | |
} | |
execmem_bytes = execmem = get_rwx_page(); | |
/* fill with RET */ | |
memset(execmem, 0xC3, PAGE_SIZE); | |
/* create the fasttrap probe */ | |
fasttrap_probe_spec_t probe; | |
probe.ftps_pid = getpid(); | |
/* These two are Mac-specific. Just ftps_type = DTFTP_OFFSETS on | |
* Solaris */ | |
probe.ftps_provider_type = DTFTP_PROVIDER_PID; | |
probe.ftps_probe_type = DTFTP_OFFSETS; | |
/* Just dummy names for now. */ | |
const char *funcname = "testfunc"; | |
const char *modname = "testmod"; | |
strcpy((char*)&probe.ftps_func, funcname); | |
strcpy((char*)&probe.ftps_mod, modname); | |
probe.ftps_pc = (uintptr_t)execmem; | |
probe.ftps_size = 1; /* just the RET */ | |
probe.ftps_noffs = 1; | |
probe.ftps_offs[0] = 0; /* offset 0; i.e., just that instruction */ | |
if (ioctl(fd, FASTTRAPIOC_MAKEPROBE, &probe) < 0) | |
err(1, "ioctl FASTTRAPIOC_MAKEPROBE"); | |
printf("Created probe 'pid%d:%s:%s:0'\n", (int)getpid(), modname, funcname); | |
/* just repeatedly fire our probe */ | |
for (;;) { | |
usleep(500 * 1000); /* don't spin too fast */ | |
/* trigger dynamically created function */ | |
(*(void (*)(void))execmem)(); | |
/* TODO: could use FASTTRAP_INSTR instead of hardcoding | |
* 0xCC, but whatevs */ | |
/* If instr is the INT3 trap instruction */ | |
if (execmem_bytes[0] == 0xCC) | |
printf("Probe is enabled\n"); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment