|
|
|
|
|
|
|
|
|
#include "usdt_internal.h" |
|
|
|
#ifdef __APPLE__ |
|
|
|
uint32_t |
|
usdt_probe_offset(usdt_probe_t *probe, char *dof, uint8_t argc) |
|
{ |
|
uint32_t offset; |
|
#ifdef __x86_64__ |
|
offset = ((uint64_t) probe->probe_addr - (uint64_t) dof + 2); |
|
#elif __i386__ |
|
offset = ((uint32_t) probe->probe_addr - (uint32_t) dof + 2); |
|
#else |
|
#error "only x86_64 and i386 supported" |
|
#endif |
|
return (offset); |
|
} |
|
|
|
uint32_t |
|
usdt_is_enabled_offset(usdt_probe_t *probe, char *dof) |
|
{ |
|
uint32_t offset; |
|
#ifdef __x86_64__ |
|
offset = ((uint64_t) probe->isenabled_addr - (uint64_t) dof + 6); |
|
#elif __i386__ |
|
offset = ((uint32_t) probe->isenabled_addr - (uint32_t) dof + 6); |
|
#else |
|
#error "only x86_64 and i386 supported" |
|
#endif |
|
return (offset); |
|
} |
|
|
|
#elif defined __linux__ |
|
|
|
uint32_t |
|
usdt_probe_offset(usdt_probe_t *probe, char *dof, uint8_t argc) |
|
{ |
|
return (16); |
|
} |
|
|
|
uint32_t |
|
usdt_is_enabled_offset(usdt_probe_t *probe, char *dof) |
|
{ |
|
return (10); |
|
} |
|
|
|
#else |
|
|
|
uint32_t |
|
usdt_probe_offset(usdt_probe_t *probe, char *dof, uint8_t argc) |
|
{ |
|
return (16); |
|
} |
|
|
|
uint32_t |
|
usdt_is_enabled_offset(usdt_probe_t *probe, char *dof) |
|
{ |
|
return (8); |
|
} |
|
|
|
#endif |
|
|
|
int |
|
usdt_create_tracepoints(usdt_probe_t *probe) |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t size; |
|
#ifdef __linux__ |
|
int fd; |
|
char tmp[20] = "/tmp/libusdtXXXXXX"; |
|
|
|
if ((fd = mkstemp(tmp)) < 0) |
|
return (-1); |
|
if (unlink(tmp) < 0) |
|
return (-1); |
|
if (write(fd, "\0", FUNC_SIZE) < FUNC_SIZE) |
|
return (-1); |
|
|
|
probe->isenabled_addr = (int (*)())mmap(NULL, FUNC_SIZE, |
|
PROT_READ | PROT_WRITE | PROT_EXEC, |
|
MAP_PRIVATE, fd, 0); |
|
#else |
|
probe->isenabled_addr = (int (*)())valloc(FUNC_SIZE); |
|
#endif |
|
if (probe->isenabled_addr == NULL) |
|
return (-1); |
|
|
|
|
|
size = ((char *)usdt_tracepoint_end - (char *)usdt_tracepoint_isenabled); |
|
assert(size < FUNC_SIZE); |
|
|
|
size = ((char *)usdt_tracepoint_probe - (char *)usdt_tracepoint_isenabled); |
|
probe->probe_addr = (char *)probe->isenabled_addr + size; |
|
|
|
memcpy((void *)probe->isenabled_addr, |
|
(const void *)usdt_tracepoint_isenabled, FUNC_SIZE); |
|
|
|
#ifdef __linux__ |
|
mprotect((void *)probe->isenabled_addr, FUNC_SIZE, |
|
PROT_READ | PROT_EXEC); |
|
#else |
|
mprotect((void *)probe->isenabled_addr, FUNC_SIZE, |
|
PROT_READ | PROT_WRITE | PROT_EXEC); |
|
#endif |
|
|
|
return (0); |
|
} |
|
|
|
void |
|
usdt_free_tracepoints(usdt_probe_t *probe) |
|
{ |
|
#ifdef __linux__ |
|
(void) munmap(probe->isenabled_addr, FUNC_SIZE); |
|
#else |
|
free(probe->isenabled_addr); |
|
#endif |
|
} |
|
|