msan_origin.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. //===-- msan_origin.h ----------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Origin id utils.
  10. //===----------------------------------------------------------------------===//
  11. #ifndef MSAN_ORIGIN_H
  12. #define MSAN_ORIGIN_H
  13. #include "sanitizer_common/sanitizer_stackdepot.h"
  14. #include "msan_chained_origin_depot.h"
  15. namespace __msan {
  16. // Origin handling.
  17. //
  18. // Origin is a 32-bit identifier that is attached to any uninitialized value in
  19. // the program and describes, more or less exactly, how this memory came to be
  20. // uninitialized.
  21. //
  22. // There are 3 kinds of origin ids:
  23. // 1xxx xxxx xxxx xxxx heap origin id
  24. // 0000 xxxx xxxx xxxx stack origin id
  25. // 0zzz xxxx xxxx xxxx chained origin id
  26. //
  27. // Heap origin id describes a heap memory allocation and contains (in the xxx
  28. // part) a value of StackDepot.
  29. //
  30. // Stack origin id describes a stack memory allocation and contains (in the xxx
  31. // part) an index into StackOriginDescr and StackOriginPC. We don't store a
  32. // stack trace for such origins for performance reasons.
  33. //
  34. // Chained origin id describes an event of storing an uninitialized value to
  35. // memory. The xxx part is a value of ChainedOriginDepot, which is a mapping of
  36. // (stack_id, prev_id) -> id, where
  37. // * stack_id describes the event.
  38. // StackDepot keeps a mapping between those and corresponding stack traces.
  39. // * prev_id is another origin id that describes the earlier part of the
  40. // uninitialized value history.
  41. // Following a chain of prev_id provides the full recorded history of an
  42. // uninitialized value.
  43. //
  44. // This, effectively, defines a tree (or 2 trees, see below) where nodes are
  45. // points in value history marked with origin ids, and edges are events that are
  46. // marked with stack_id.
  47. //
  48. // The "zzz" bits of chained origin id are used to store the length (or depth)
  49. // of the origin chain.
  50. class Origin {
  51. public:
  52. static bool isValidId(u32 id) { return id != 0 && id != (u32)-1; }
  53. u32 raw_id() const { return raw_id_; }
  54. bool isHeapOrigin() const {
  55. // 0xxx xxxx xxxx xxxx
  56. return raw_id_ >> kHeapShift == 0;
  57. }
  58. bool isStackOrigin() const {
  59. // 1000 xxxx xxxx xxxx
  60. return (raw_id_ >> kDepthShift) == (1 << kDepthBits);
  61. }
  62. bool isChainedOrigin() const {
  63. // 1zzz xxxx xxxx xxxx, zzz != 000
  64. return (raw_id_ >> kDepthShift) > (1 << kDepthBits);
  65. }
  66. u32 getChainedId() const {
  67. CHECK(isChainedOrigin());
  68. return raw_id_ & kChainedIdMask;
  69. }
  70. u32 getStackId() const {
  71. CHECK(isStackOrigin());
  72. return raw_id_ & kChainedIdMask;
  73. }
  74. u32 getHeapId() const {
  75. CHECK(isHeapOrigin());
  76. return raw_id_ & kHeapIdMask;
  77. }
  78. // Returns the next origin in the chain and the current stack trace.
  79. Origin getNextChainedOrigin(StackTrace *stack) const {
  80. CHECK(isChainedOrigin());
  81. u32 prev_id;
  82. u32 stack_id = ChainedOriginDepotGet(getChainedId(), &prev_id);
  83. if (stack) *stack = StackDepotGet(stack_id);
  84. return Origin(prev_id);
  85. }
  86. StackTrace getStackTraceForHeapOrigin() const {
  87. return StackDepotGet(getHeapId());
  88. }
  89. static Origin CreateStackOrigin(u32 id) {
  90. CHECK((id & kStackIdMask) == id);
  91. return Origin((1 << kHeapShift) | id);
  92. }
  93. static Origin CreateHeapOrigin(StackTrace *stack) {
  94. u32 stack_id = StackDepotPut(*stack);
  95. CHECK(stack_id);
  96. CHECK((stack_id & kHeapIdMask) == stack_id);
  97. return Origin(stack_id);
  98. }
  99. static Origin CreateChainedOrigin(Origin prev, StackTrace *stack) {
  100. int depth = prev.isChainedOrigin() ? prev.depth() : 0;
  101. // depth is the length of the chain minus 1.
  102. // origin_history_size of 0 means unlimited depth.
  103. if (flags()->origin_history_size > 0) {
  104. if (depth + 1 >= flags()->origin_history_size) {
  105. return prev;
  106. } else {
  107. ++depth;
  108. CHECK(depth < (1 << kDepthBits));
  109. }
  110. }
  111. StackDepotHandle h = StackDepotPut_WithHandle(*stack);
  112. if (!h.valid()) return prev;
  113. if (flags()->origin_history_per_stack_limit > 0) {
  114. int use_count = h.use_count();
  115. if (use_count > flags()->origin_history_per_stack_limit) return prev;
  116. }
  117. u32 chained_id;
  118. bool inserted = ChainedOriginDepotPut(h.id(), prev.raw_id(), &chained_id);
  119. CHECK((chained_id & kChainedIdMask) == chained_id);
  120. if (inserted && flags()->origin_history_per_stack_limit > 0)
  121. h.inc_use_count_unsafe();
  122. return Origin((1 << kHeapShift) | (depth << kDepthShift) | chained_id);
  123. }
  124. static Origin FromRawId(u32 id) {
  125. return Origin(id);
  126. }
  127. private:
  128. static const int kDepthBits = 3;
  129. static const int kDepthShift = 32 - kDepthBits - 1;
  130. static const int kHeapShift = 31;
  131. static const u32 kChainedIdMask = ((u32)-1) >> (32 - kDepthShift);
  132. static const u32 kStackIdMask = ((u32)-1) >> (32 - kDepthShift);
  133. static const u32 kHeapIdMask = ((u32)-1) >> (32 - kHeapShift);
  134. u32 raw_id_;
  135. explicit Origin(u32 raw_id) : raw_id_(raw_id) {}
  136. int depth() const {
  137. CHECK(isChainedOrigin());
  138. return (raw_id_ >> kDepthShift) & ((1 << kDepthBits) - 1);
  139. }
  140. public:
  141. static const int kMaxDepth = (1 << kDepthBits) - 1;
  142. };
  143. } // namespace __msan
  144. #endif // MSAN_ORIGIN_H