valgrind.odin 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. //+build amd64
  2. package sys_valgrind
  3. import "base:intrinsics"
  4. Client_Request :: enum uintptr {
  5. Running_On_Valgrind = 4097,
  6. Discard_Translations = 4098,
  7. Client_Call0 = 4353,
  8. Client_Call1 = 4354,
  9. Client_Call2 = 4355,
  10. Client_Call3 = 4356,
  11. Count_Errors = 4609,
  12. Gdb_Monitor_Command = 4610,
  13. Malloc_Like_Block = 4865,
  14. Resize_Inplace_Block = 4875,
  15. Free_Like_Block = 4866,
  16. Create_Mem_Pool = 4867,
  17. Destroy_Mem_Pool = 4868,
  18. Mem_Pool_Alloc = 4869,
  19. Mem_Pool_Free = 4870,
  20. Mem_Pool_Trim = 4871,
  21. Move_Mem_Pool = 4872,
  22. Mem_Pool_Change = 4873,
  23. Mem_Pool_Exists = 4874,
  24. Printf = 5121,
  25. Printf_Backtrace = 5122,
  26. Printf_Valist_By_Ref = 5123,
  27. Printf_Backtrace_Valist_By_Ref = 5124,
  28. Stack_Register = 5377,
  29. Stack_Deregister = 5378,
  30. Stack_Change = 5379,
  31. Load_Pdb_Debug_Info = 5633,
  32. Map_Ip_To_Src_Loc = 5889,
  33. Change_Err_Disablement = 6145,
  34. Vex_Init_For_Iri = 6401,
  35. Inner_Threads = 6402,
  36. }
  37. @(require_results)
  38. client_request_expr :: #force_inline proc "c" (default: uintptr, request: Client_Request, a0, a1, a2, a3, a4: uintptr) -> uintptr {
  39. return intrinsics.valgrind_client_request(default, uintptr(request), a0, a1, a2, a3, a4)
  40. }
  41. client_request_stmt :: #force_inline proc "c" (request: Client_Request, a0, a1, a2, a3, a4: uintptr) {
  42. _ = intrinsics.valgrind_client_request(0, uintptr(request), a0, a1, a2, a3, a4)
  43. }
  44. // Returns the number of Valgrinds this code is running under
  45. // 0 - running natively
  46. // 1 - running under Valgrind
  47. // 2 - running under Valgrind which is running under another Valgrind
  48. running_on_valgrind :: proc "c" () -> uint {
  49. return uint(client_request_expr(0, .Running_On_Valgrind, 0, 0, 0, 0, 0))
  50. }
  51. // Discard translation of code in the slice qzz. Useful if you are debugging a JIT-er or some such,
  52. // since it provides a way to make sure valgrind will retranslate the invalidated area.
  53. discard_translations :: proc "c" (qzz: []byte) {
  54. client_request_stmt(.Discard_Translations, uintptr(raw_data(qzz)), uintptr(len(qzz)), 0, 0, 0)
  55. }
  56. non_simd_call0 :: proc "c" (p: proc "c" (uintptr) -> uintptr) -> uintptr {
  57. return client_request_expr(0, .Client_Call0, uintptr(rawptr(p)), 0, 0, 0, 0)
  58. }
  59. non_simd_call1 :: proc "c" (p: proc "c" (uintptr, uintptr) -> uintptr, a0: uintptr) -> uintptr {
  60. return client_request_expr(0, .Client_Call1, uintptr(rawptr(p)), a0, 0, 0, 0)
  61. }
  62. non_simd_call2 :: proc "c" (p: proc "c" (uintptr, uintptr, uintptr) -> uintptr, a0, a1: uintptr) -> uintptr {
  63. return client_request_expr(0, .Client_Call2, uintptr(rawptr(p)), a0, a1, 0, 0)
  64. }
  65. non_simd_call3 :: proc "c" (p: proc "c" (uintptr, uintptr, uintptr, uintptr) -> uintptr, a0, a1, a2: uintptr) -> uintptr {
  66. return client_request_expr(0, .Client_Call3, uintptr(rawptr(p)), a0, a1, a2, 0)
  67. }
  68. // Counts the number of errors that have been recorded by a tool.
  69. count_errrors :: proc "c" () -> uint {
  70. return uint(client_request_expr(0, .Count_Errors, 0, 0, 0, 0, 0))
  71. }
  72. monitor_command :: proc "c" (command: cstring) -> bool {
  73. return 0 != client_request_expr(0, .Gdb_Monitor_Command, uintptr(rawptr(command)), 0, 0, 0, 0)
  74. }
  75. malloc_like_block :: proc "c" (mem: []byte, rz_b: uintptr, is_zeroed: bool) {
  76. client_request_stmt(.Malloc_Like_Block, uintptr(raw_data(mem)), uintptr(len(mem)), rz_b, uintptr(is_zeroed), 0)
  77. }
  78. resize_inplace_block :: proc "c" (old_mem: []byte, new_size: uint, rz_b: uintptr) {
  79. client_request_stmt(.Resize_Inplace_Block, uintptr(raw_data(old_mem)), uintptr(len(old_mem)), uintptr(new_size), rz_b, 0)
  80. }
  81. free_like_block :: proc "c" (addr: rawptr, rz_b: uintptr) {
  82. client_request_stmt(.Free_Like_Block, uintptr(addr), rz_b, 0, 0, 0)
  83. }
  84. Mem_Pool_Flags :: distinct bit_set[Mem_Pool_Flag; uintptr]
  85. Mem_Pool_Flag :: enum uintptr {
  86. Auto_Free = 0,
  87. Meta_Pool = 1,
  88. }
  89. // Create a memory pool.
  90. create_mem_pool :: proc "c" (pool: rawptr, rz_b: uintptr, is_zeroed: bool, flags: Mem_Pool_Flags) {
  91. client_request_stmt(.Create_Mem_Pool, uintptr(pool), rz_b, uintptr(is_zeroed), transmute(uintptr)flags, 0)
  92. }
  93. // Destroy a memory pool.
  94. destroy_mem_pool :: proc "c" (pool: rawptr) {
  95. client_request_stmt(.Destroy_Mem_Pool, uintptr(pool), 0, 0, 0, 0)
  96. }
  97. // Associate a section of memory with a memory pool.
  98. mem_pool_alloc :: proc "c" (pool: rawptr, mem: []byte) {
  99. client_request_stmt(.Mem_Pool_Alloc, uintptr(pool), uintptr(raw_data(mem)), uintptr(len(mem)), 0, 0)
  100. }
  101. // Disassociate a section of memory from a memory pool.
  102. mem_pool_free :: proc "c" (pool: rawptr, addr: rawptr) {
  103. client_request_stmt(.Mem_Pool_Free, uintptr(pool), uintptr(addr), 0, 0, 0)
  104. }
  105. // Disassociate parts of a section of memory outside a particular range.
  106. mem_pool_trim :: proc "c" (pool: rawptr, mem: []byte) {
  107. client_request_stmt(.Mem_Pool_Trim, uintptr(pool), uintptr(raw_data(mem)), uintptr(len(mem)), 0, 0)
  108. }
  109. // Resize and/or move a section of memory associated with a memory pool.
  110. move_mem_pool :: proc "c" (pool_a, pool_b: rawptr) {
  111. client_request_stmt(.Move_Mem_Pool, uintptr(pool_a), uintptr(pool_b), 0, 0, 0)
  112. }
  113. // Resize and/or move a section of memory associated with a memory pool.
  114. mem_pool_change :: proc "c" (pool: rawptr, addr_a: rawptr, mem: []byte) {
  115. client_request_stmt(.Mem_Pool_Change, uintptr(pool), uintptr(addr_a), uintptr(raw_data(mem)), uintptr(len(mem)), 0)
  116. }
  117. // Return true if a memory pool exists
  118. mem_pool_exists :: proc "c" (pool: rawptr) -> bool {
  119. return 0 != client_request_expr(0, .Mem_Pool_Exists, uintptr(pool), 0, 0, 0, 0)
  120. }
  121. // Mark a section of memory as being a stack. Returns a stack id.
  122. stack_register :: proc "c" (stack: []byte) -> (stack_id: uintptr) {
  123. ptr := uintptr(raw_data(stack))
  124. return client_request_expr(0, .Stack_Register, ptr, ptr+uintptr(len(stack)), 0, 0, 0)
  125. }
  126. // Unmark a section of memory associated with a stack id as being a stack.
  127. stack_deregister :: proc "c" (id: uintptr) {
  128. client_request_stmt(.Stack_Deregister, id, 0, 0, 0, 0)
  129. }
  130. // Change the start and end address of the stack id with the `new_stack` slice.
  131. stack_change :: proc "c" (id: uint, new_stack: []byte) {
  132. ptr := uintptr(raw_data(new_stack))
  133. client_request_stmt(.Stack_Change, uintptr(id), ptr, ptr + uintptr(len(new_stack)), 0, 0)
  134. }
  135. // Disable error reporting for the current thread/
  136. // It behaves in a stack-like way, meaning you can safely call this multiple times
  137. // given that `enable_error_reporting()` is called the same number of times to
  138. // re-enable the error reporting.
  139. // The first call of this macro disables reporting.
  140. // Subsequent calls have no effect except to increase the number of `enable_error_reporting()`
  141. // calls needed to re-enable reporting.
  142. // Child threads do not inherit this setting from their parents;
  143. // they are always created with reporting enabled.
  144. disable_error_reporting :: proc "c" () {
  145. client_request_stmt(.Change_Err_Disablement, 1, 0, 0, 0, 0)
  146. }
  147. // Re-enable error reporting
  148. enable_error_reporting :: proc "c" () {
  149. client_request_stmt(.Change_Err_Disablement, ~uintptr(0), 0, 0, 0, 0)
  150. }
  151. inner_threads :: proc "c" (qzz: rawptr) {
  152. client_request_stmt(.Inner_Threads, uintptr(qzz), 0, 0, 0, 0)
  153. }
  154. // Map a code address to a source file name and line number.
  155. // `buf64` must point to a 64-byte buffer in the caller's address space.
  156. // The result will be dumped in there and is guaranteed to be zero terminated.
  157. // If no info is found, the first byte is set to zero.
  158. map_ip_to_src_loc :: proc "c" (addr: rawptr, buf64: ^[64]byte) -> uintptr {
  159. return client_request_expr(0, .Map_Ip_To_Src_Loc, uintptr(addr), uintptr(buf64), 0, 0, 0)
  160. }