msan8.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Copyright 2021 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package main
  5. /*
  6. #include <pthread.h>
  7. #include <signal.h>
  8. #include <stdint.h>
  9. #include <sanitizer/msan_interface.h>
  10. // cgoTracebackArg is the type of the argument passed to msanGoTraceback.
  11. struct cgoTracebackArg {
  12. uintptr_t context;
  13. uintptr_t sigContext;
  14. uintptr_t* buf;
  15. uintptr_t max;
  16. };
  17. // msanGoTraceback is registered as the cgo traceback function.
  18. // This will be called when a signal occurs.
  19. void msanGoTraceback(void* parg) {
  20. struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
  21. arg->buf[0] = 0;
  22. }
  23. // msanGoWait will be called with all registers undefined as far as
  24. // msan is concerned. It just waits for a signal.
  25. // Because the registers are msan-undefined, the signal handler will
  26. // be invoked with all registers msan-undefined.
  27. __attribute__((noinline))
  28. void msanGoWait(unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a6) {
  29. sigset_t mask;
  30. sigemptyset(&mask);
  31. sigsuspend(&mask);
  32. }
  33. // msanGoSignalThread is the thread ID of the msanGoLoop thread.
  34. static pthread_t msanGoSignalThread;
  35. // msanGoSignalThreadSet is used to record that msanGoSignalThread
  36. // has been initialized. This is accessed atomically.
  37. static int32_t msanGoSignalThreadSet;
  38. // uninit is explicitly poisoned, so that we can make all registers
  39. // undefined by calling msanGoWait.
  40. static unsigned long uninit;
  41. // msanGoLoop loops calling msanGoWait, with the arguments passed
  42. // such that msan thinks that they are undefined. msan permits
  43. // undefined values to be used as long as they are not used to
  44. // for conditionals or for memory access.
  45. void msanGoLoop() {
  46. int i;
  47. msanGoSignalThread = pthread_self();
  48. __atomic_store_n(&msanGoSignalThreadSet, 1, __ATOMIC_SEQ_CST);
  49. // Force uninit to be undefined for msan.
  50. __msan_poison(&uninit, sizeof uninit);
  51. for (i = 0; i < 100; i++) {
  52. msanGoWait(uninit, uninit, uninit, uninit, uninit, uninit);
  53. }
  54. }
  55. // msanGoReady returns whether msanGoSignalThread is set.
  56. int msanGoReady() {
  57. return __atomic_load_n(&msanGoSignalThreadSet, __ATOMIC_SEQ_CST) != 0;
  58. }
  59. // msanGoSendSignal sends a signal to the msanGoLoop thread.
  60. void msanGoSendSignal() {
  61. pthread_kill(msanGoSignalThread, SIGWINCH);
  62. }
  63. */
  64. import "C"
  65. import (
  66. "runtime"
  67. "time"
  68. )
  69. func main() {
  70. runtime.SetCgoTraceback(0, C.msanGoTraceback, nil, nil)
  71. c := make(chan bool)
  72. go func() {
  73. defer func() { c <- true }()
  74. C.msanGoLoop()
  75. }()
  76. for C.msanGoReady() == 0 {
  77. time.Sleep(time.Microsecond)
  78. }
  79. loop:
  80. for {
  81. select {
  82. case <-c:
  83. break loop
  84. default:
  85. C.msanGoSendSignal()
  86. time.Sleep(time.Microsecond)
  87. }
  88. }
  89. }