| |
| |
| |
|
|
| #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 |
| } |
|
|