Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

usdt_probe.c 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Copyright (c) 2012, Chris Andrews. All rights reserved.
  3. */
  4. #include "usdt_internal.h"
  5. #ifdef __APPLE__
  6. uint32_t
  7. usdt_probe_offset(usdt_probe_t *probe, char *dof, uint8_t argc)
  8. {
  9. uint32_t offset;
  10. #ifdef __x86_64__
  11. offset = ((uint64_t) probe->probe_addr - (uint64_t) dof + 2);
  12. #elif __i386__
  13. offset = ((uint32_t) probe->probe_addr - (uint32_t) dof + 2);
  14. #else
  15. #error "only x86_64 and i386 supported"
  16. #endif
  17. return (offset);
  18. }
  19. uint32_t
  20. usdt_is_enabled_offset(usdt_probe_t *probe, char *dof)
  21. {
  22. uint32_t offset;
  23. #ifdef __x86_64__
  24. offset = ((uint64_t) probe->isenabled_addr - (uint64_t) dof + 6);
  25. #elif __i386__
  26. offset = ((uint32_t) probe->isenabled_addr - (uint32_t) dof + 6);
  27. #else
  28. #error "only x86_64 and i386 supported"
  29. #endif
  30. return (offset);
  31. }
  32. #elif defined __linux__
  33. uint32_t
  34. usdt_probe_offset(usdt_probe_t *probe, char *dof, uint8_t argc)
  35. {
  36. return (16);
  37. }
  38. uint32_t
  39. usdt_is_enabled_offset(usdt_probe_t *probe, char *dof)
  40. {
  41. return (10);
  42. }
  43. #else /* solaris and freebsd */
  44. uint32_t
  45. usdt_probe_offset(usdt_probe_t *probe, char *dof, uint8_t argc)
  46. {
  47. return (16);
  48. }
  49. uint32_t
  50. usdt_is_enabled_offset(usdt_probe_t *probe, char *dof)
  51. {
  52. return (8);
  53. }
  54. #endif
  55. int
  56. usdt_create_tracepoints(usdt_probe_t *probe)
  57. {
  58. /* Prepare the tracepoints - for each probe, a separate chunk
  59. * of memory with the tracepoint code copied into it, to give
  60. * us unique addresses for each tracepoint.
  61. *
  62. * On Oracle Linux, this must be an mmapped file because USDT
  63. * probes there are implemented as uprobes, which are
  64. * addressed by inode and offset. The file used is a small
  65. * mkstemp'd file we immediately unlink.
  66. *
  67. * Elsewhere, we can use the heap directly because USDT will
  68. * instrument any memory mapped by the process.
  69. */
  70. size_t size;
  71. #ifdef __linux__
  72. int fd;
  73. char tmp[20] = "/tmp/libusdtXXXXXX";
  74. if ((fd = mkstemp(tmp)) < 0)
  75. return (-1);
  76. if (unlink(tmp) < 0)
  77. return (-1);
  78. if (write(fd, "\0", FUNC_SIZE) < FUNC_SIZE)
  79. return (-1);
  80. probe->isenabled_addr = (int (*)())mmap(NULL, FUNC_SIZE,
  81. PROT_READ | PROT_WRITE | PROT_EXEC,
  82. MAP_PRIVATE, fd, 0);
  83. #else
  84. probe->isenabled_addr = (int (*)())valloc(FUNC_SIZE);
  85. #endif
  86. if (probe->isenabled_addr == NULL)
  87. return (-1);
  88. /* ensure that the tracepoints will fit the heap we're allocating */
  89. size = ((char *)usdt_tracepoint_end - (char *)usdt_tracepoint_isenabled);
  90. assert(size < FUNC_SIZE);
  91. size = ((char *)usdt_tracepoint_probe - (char *)usdt_tracepoint_isenabled);
  92. probe->probe_addr = (char *)probe->isenabled_addr + size;
  93. memcpy((void *)probe->isenabled_addr,
  94. (const void *)usdt_tracepoint_isenabled, FUNC_SIZE);
  95. #ifdef __linux__
  96. mprotect((void *)probe->isenabled_addr, FUNC_SIZE,
  97. PROT_READ | PROT_EXEC);
  98. #else
  99. mprotect((void *)probe->isenabled_addr, FUNC_SIZE,
  100. PROT_READ | PROT_WRITE | PROT_EXEC);
  101. #endif
  102. return (0);
  103. }
  104. void
  105. usdt_free_tracepoints(usdt_probe_t *probe)
  106. {
  107. #ifdef __linux__
  108. (void) munmap(probe->isenabled_addr, FUNC_SIZE);
  109. #else
  110. free(probe->isenabled_addr);
  111. #endif
  112. }