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_dof_file.c 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * Copyright (c) 2012, Chris Andrews. All rights reserved.
  3. */
  4. #include "usdt_internal.h"
  5. #include <sys/ioctl.h>
  6. static uint8_t
  7. dof_version(uint8_t header_version)
  8. {
  9. uint8_t dof_version;
  10. /* DOF versioning: Apple always needs version 3, but Solaris can use
  11. 1 or 2 depending on whether is-enabled probes are needed. */
  12. #ifdef __APPLE__
  13. dof_version = DOF_VERSION_3;
  14. #else
  15. switch(header_version) {
  16. case 1:
  17. dof_version = DOF_VERSION_1;
  18. break;
  19. case 2:
  20. dof_version = DOF_VERSION_2;
  21. break;
  22. default:
  23. dof_version = DOF_VERSION;
  24. }
  25. #endif
  26. return dof_version;
  27. }
  28. #ifdef __APPLE__
  29. static const char *helper = "/dev/dtracehelper";
  30. static int
  31. load_dof(int fd, dof_helper_t *dh)
  32. {
  33. int ret;
  34. uint8_t buffer[sizeof(dof_ioctl_data_t) + sizeof(dof_helper_t)];
  35. dof_ioctl_data_t* ioctlData = (dof_ioctl_data_t*)buffer;
  36. user_addr_t val;
  37. ioctlData->dofiod_count = 1;
  38. memcpy(&ioctlData->dofiod_helpers[0], dh, sizeof(dof_helper_t));
  39. val = (user_addr_t)(unsigned long)ioctlData;
  40. ret = ioctl(fd, DTRACEHIOC_ADDDOF, &val);
  41. if (ret < 0)
  42. return ret;
  43. return (int)(ioctlData->dofiod_helpers[0].dofhp_dof);
  44. }
  45. #else /* Solaris and FreeBSD */
  46. /* ignore Sol10 GA ... */
  47. static const char *helper = "/dev/dtrace/helper";
  48. static int
  49. load_dof(int fd, dof_helper_t *dh)
  50. {
  51. int ret;
  52. ret = ioctl(fd, DTRACEHIOC_ADDDOF, dh);
  53. #if defined(__FreeBSD__) && __FreeBSD__ <= 10
  54. if (ret != -1)
  55. ret = dh ->gen;
  56. #endif
  57. return ret;
  58. }
  59. #endif
  60. static void
  61. pad_section(usdt_dof_section_t *sec)
  62. {
  63. size_t i, pad;
  64. if (sec->align > 1) {
  65. i = sec->offset % sec->align;
  66. if (i > 0) {
  67. pad = sec->align - i;
  68. sec->offset = (pad + sec->offset);
  69. sec->pad = pad;
  70. }
  71. }
  72. }
  73. static void
  74. dof_header(dof_hdr_t *header)
  75. {
  76. int i;
  77. header->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0;
  78. header->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1;
  79. header->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2;
  80. header->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3;
  81. header->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_NATIVE;
  82. header->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE;
  83. header->dofh_ident[DOF_ID_VERSION] = dof_version(2);
  84. header->dofh_ident[DOF_ID_DIFVERS] = DIF_VERSION;
  85. header->dofh_ident[DOF_ID_DIFIREG] = DIF_DIR_NREGS;
  86. header->dofh_ident[DOF_ID_DIFTREG] = DIF_DTR_NREGS;
  87. for (i = DOF_ID_PAD; i < DOF_ID_SIZE; i++)
  88. header->dofh_ident[i] = 0;
  89. header->dofh_flags = 0;
  90. header->dofh_hdrsize = sizeof(dof_hdr_t);
  91. header->dofh_secsize = sizeof(dof_sec_t);
  92. header->dofh_secoff = sizeof(dof_hdr_t);
  93. header->dofh_loadsz = 0;
  94. header->dofh_filesz = 0;
  95. header->dofh_pad = 0;
  96. }
  97. static size_t
  98. add_header(usdt_dof_file_t *file, size_t offset, usdt_dof_section_t *section)
  99. {
  100. dof_sec_t header;
  101. header.dofs_flags = section->flags;
  102. header.dofs_type = section->type;
  103. header.dofs_offset = section->offset;
  104. header.dofs_size = section->size;
  105. header.dofs_entsize = section->entsize;
  106. header.dofs_align = section->align;
  107. memcpy((file->dof + offset), &header, sizeof(dof_sec_t));
  108. return (offset + sizeof(dof_sec_t));
  109. }
  110. static size_t
  111. add_section(usdt_dof_file_t *file, size_t offset, usdt_dof_section_t *section)
  112. {
  113. if (section->pad > 0) {
  114. /* maximum padding required is 7 */
  115. memcpy((file->dof + offset), "\0\0\0\0\0\0\0", section->pad);
  116. offset += section->pad;
  117. }
  118. memcpy((file->dof + offset), section->data, section->size);
  119. return (offset + section->size);
  120. }
  121. int
  122. usdt_dof_file_unload(usdt_dof_file_t *file)
  123. {
  124. int fd, ret;
  125. if ((fd = open(helper, O_RDWR)) < 0)
  126. return (-1);
  127. #ifdef __FreeBSD__
  128. ret = ioctl(fd, DTRACEHIOC_REMOVE, &file->gen);
  129. #else
  130. ret = ioctl(fd, DTRACEHIOC_REMOVE, file->gen);
  131. #endif
  132. if (ret < 0)
  133. return (-1);
  134. if ((close(fd)) < 0)
  135. return (-1);
  136. return (0);
  137. }
  138. int
  139. usdt_dof_file_load(usdt_dof_file_t *file, const char *module)
  140. {
  141. dof_helper_t dh;
  142. dof_hdr_t *dof;
  143. int fd;
  144. dof = (dof_hdr_t *) file->dof;
  145. dh.dofhp_dof = (uintptr_t)dof;
  146. dh.dofhp_addr = (uintptr_t)dof;
  147. #if __FreeBSD__ >= 11
  148. dh.dofhp_pid = getpid();
  149. #endif
  150. (void) strncpy(dh.dofhp_mod, module, sizeof (dh.dofhp_mod));
  151. if ((fd = open(helper, O_RDWR)) < 0)
  152. return (-1);
  153. file->gen = load_dof(fd, &dh);
  154. if ((close(fd)) < 0)
  155. return (-1);
  156. if (file->gen < 0)
  157. return (-1);
  158. return (0);
  159. }
  160. void
  161. usdt_dof_file_append_section(usdt_dof_file_t *file, usdt_dof_section_t *section)
  162. {
  163. usdt_dof_section_t *s;
  164. if (file->sections == NULL) {
  165. file->sections = section;
  166. }
  167. else {
  168. for (s = file->sections; (s->next != NULL); s = s->next) ;
  169. s->next = section;
  170. }
  171. }
  172. void
  173. usdt_dof_file_generate(usdt_dof_file_t *file, usdt_strtab_t *strtab)
  174. {
  175. dof_hdr_t header;
  176. uint64_t filesz;
  177. uint64_t loadsz;
  178. usdt_dof_section_t *sec;
  179. size_t offset;
  180. dof_header(&header);
  181. header.dofh_secnum = 6;
  182. filesz = sizeof(dof_hdr_t) + (sizeof(dof_sec_t) * header.dofh_secnum);
  183. loadsz = filesz;
  184. strtab->offset = filesz;
  185. pad_section((usdt_dof_section_t *)strtab);
  186. filesz += strtab->size + strtab->pad;
  187. if (strtab->flags & 1)
  188. loadsz += strtab->size + strtab->pad;
  189. for (sec = file->sections; sec != NULL; sec = sec->next) {
  190. sec->offset = filesz;
  191. pad_section(sec);
  192. filesz += sec->size + sec->pad;
  193. if (sec->flags & 1)
  194. loadsz += sec->size + sec->pad;
  195. }
  196. header.dofh_loadsz = loadsz;
  197. header.dofh_filesz = filesz;
  198. memcpy(file->dof, &header, sizeof(dof_hdr_t));
  199. offset = sizeof(dof_hdr_t);
  200. offset = add_header(file, offset, (usdt_dof_section_t *)strtab);
  201. for (sec = file->sections; sec != NULL; sec = sec->next)
  202. offset = add_header(file, offset, sec);
  203. offset = add_section(file, offset, (usdt_dof_section_t *)strtab);
  204. for (sec = file->sections; sec != NULL; sec = sec->next)
  205. offset = add_section(file, offset, sec);
  206. }
  207. usdt_dof_file_t *
  208. usdt_dof_file_init(usdt_provider_t *provider, size_t size)
  209. {
  210. usdt_dof_file_t *file;
  211. if ((file = malloc(sizeof(*file))) == NULL) {
  212. usdt_error(provider, USDT_ERROR_MALLOC);
  213. return (NULL);
  214. }
  215. if ((file->dof = valloc(size)) == NULL) {
  216. usdt_error(provider, USDT_ERROR_VALLOC);
  217. return (NULL);
  218. }
  219. file->sections = NULL;
  220. file->size = size;
  221. return (file);
  222. }
  223. void
  224. usdt_dof_file_free(usdt_dof_file_t *file)
  225. {
  226. free(file->dof);
  227. free(file);
  228. }