summaryrefslogtreecommitdiff
path: root/lib/msan/msan_origin.h
blob: a4156507ba9aaa8d414a6bc423eed6d566c895c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//===-- msan_origin.h ----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Origin id utils.
//===----------------------------------------------------------------------===//
#ifndef MSAN_ORIGIN_H
#define MSAN_ORIGIN_H

namespace __msan {

// Origin handling.
//
// Origin is a 32-bit identifier that is attached to any uninitialized value in
// the program and describes, more or less exactly, how this memory came to be
// uninitialized.
//
// Origin ids are values of ChainedOriginDepot, which is a mapping of (stack_id,
// prev_id) -> id, where
//  * stack_id describes an event in the program, usually a memory store.
//    StackDepot keeps a mapping between those and corresponding stack traces.
//  * prev_id is another origin id that describes the earlier part of the
//    uninitialized value history.
// Following a chain of prev_id provides the full recorded history of an
// uninitialized value.
//
// This, effectively, defines a tree (or 2 trees, see below) where nodes are
// points in value history marked with origin ids, and edges are events that are
// marked with stack_id.
//
// There are 2 special root origin ids:
// * kHeapRoot - an origin with prev_id == kHeapRoot describes an event of
//   allocating memory from heap.
// * kStackRoot - an origin with prev_id == kStackRoot describes an event of
//   allocating memory from stack (i.e. on function entry).
// Note that ChainedOriginDepot does not store any node for kHeapRoot or
// kStackRoot. These are just special id values.
//
// Three highest bits of origin id are used to store the length (or depth) of
// the origin chain. Special depth value of 0 means unlimited.

class Origin {
 public:
  static const int kDepthBits = 3;
  static const int kDepthShift = 32 - kDepthBits;
  static const u32 kIdMask = ((u32)-1) >> (32 - kDepthShift);
  static const u32 kDepthMask = ~kIdMask;

  static const int kMaxDepth = (1 << kDepthBits) - 1;

  static const u32 kHeapRoot = (u32)-1;
  static const u32 kStackRoot = (u32)-2;

  explicit Origin(u32 raw_id) : raw_id_(raw_id) {}
  Origin(u32 id, u32 depth) : raw_id_((depth << kDepthShift) | id) {
    CHECK_EQ(this->depth(), depth);
    CHECK_EQ(this->id(), id);
  }
  int depth() const { return raw_id_ >> kDepthShift; }
  u32 id() const { return raw_id_ & kIdMask; }
  u32 raw_id() const { return raw_id_; }
  bool isStackRoot() const { return raw_id_ == kStackRoot; }
  bool isHeapRoot() const { return raw_id_ == kHeapRoot; }
  bool isValid() const { return raw_id_ != 0 && raw_id_ != (u32)-1; }

 private:
  u32 raw_id_;
};

}  // namespace __msan

#endif  // MSAN_ORIGIN_H