asan_descriptions.h revision 1.1.1.3
1//===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
2//
3// This file is distributed under the University of Illinois Open Source
4// License. See LICENSE.TXT for details.
5//
6//===----------------------------------------------------------------------===//
7//
8// This file is a part of AddressSanitizer, an address sanity checker.
9//
10// ASan-private header for asan_descriptions.cc.
11// TODO(filcab): Most struct definitions should move to the interface headers.
12//===----------------------------------------------------------------------===//
13#ifndef ASAN_DESCRIPTIONS_H
14#define ASAN_DESCRIPTIONS_H
15
16#include "asan_allocator.h"
17#include "asan_thread.h"
18#include "sanitizer_common/sanitizer_common.h"
19#include "sanitizer_common/sanitizer_report_decorator.h"
20
21namespace __asan {
22
23void DescribeThread(AsanThreadContext *context);
24static inline void DescribeThread(AsanThread *t) {
25  if (t) DescribeThread(t->context());
26}
27
28class AsanThreadIdAndName {
29 public:
30  explicit AsanThreadIdAndName(AsanThreadContext *t);
31  explicit AsanThreadIdAndName(u32 tid);
32
33  // Contains "T%tid (%name)" or "T%tid" if the name is empty.
34  const char *c_str() const { return &name[0]; }
35
36 private:
37  void Init(u32 tid, const char *tname);
38
39  char name[128];
40};
41
42class Decorator : public __sanitizer::SanitizerCommonDecorator {
43 public:
44  Decorator() : SanitizerCommonDecorator() {}
45  const char *Access() { return Blue(); }
46  const char *Location() { return Green(); }
47  const char *Allocation() { return Magenta(); }
48
49  const char *ShadowByte(u8 byte) {
50    switch (byte) {
51      case kAsanHeapLeftRedzoneMagic:
52      case kAsanArrayCookieMagic:
53        return Red();
54      case kAsanHeapFreeMagic:
55        return Magenta();
56      case kAsanStackLeftRedzoneMagic:
57      case kAsanStackMidRedzoneMagic:
58      case kAsanStackRightRedzoneMagic:
59        return Red();
60      case kAsanStackAfterReturnMagic:
61        return Magenta();
62      case kAsanInitializationOrderMagic:
63        return Cyan();
64      case kAsanUserPoisonedMemoryMagic:
65      case kAsanContiguousContainerOOBMagic:
66      case kAsanAllocaLeftMagic:
67      case kAsanAllocaRightMagic:
68        return Blue();
69      case kAsanStackUseAfterScopeMagic:
70        return Magenta();
71      case kAsanGlobalRedzoneMagic:
72        return Red();
73      case kAsanInternalHeapMagic:
74        return Yellow();
75      case kAsanIntraObjectRedzone:
76        return Yellow();
77      default:
78        return Default();
79    }
80  }
81};
82
83enum ShadowKind : u8 {
84  kShadowKindLow,
85  kShadowKindGap,
86  kShadowKindHigh,
87};
88static const char *const ShadowNames[] = {"low shadow", "shadow gap",
89                                          "high shadow"};
90
91struct ShadowAddressDescription {
92  uptr addr;
93  ShadowKind kind;
94  u8 shadow_byte;
95
96  void Print() const;
97};
98
99bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
100bool DescribeAddressIfShadow(uptr addr);
101
102enum AccessType {
103  kAccessTypeLeft,
104  kAccessTypeRight,
105  kAccessTypeInside,
106  kAccessTypeUnknown,  // This means we have an AddressSanitizer bug!
107};
108
109struct ChunkAccess {
110  uptr bad_addr;
111  sptr offset;
112  uptr chunk_begin;
113  uptr chunk_size;
114  u32 user_requested_alignment : 12;
115  u32 access_type : 2;
116  u32 alloc_type : 2;
117};
118
119struct HeapAddressDescription {
120  uptr addr;
121  uptr alloc_tid;
122  uptr free_tid;
123  u32 alloc_stack_id;
124  u32 free_stack_id;
125  ChunkAccess chunk_access;
126
127  void Print() const;
128};
129
130bool GetHeapAddressInformation(uptr addr, uptr access_size,
131                               HeapAddressDescription *descr);
132bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
133
134struct StackAddressDescription {
135  uptr addr;
136  uptr tid;
137  uptr offset;
138  uptr frame_pc;
139  uptr access_size;
140  const char *frame_descr;
141
142  void Print() const;
143};
144
145bool GetStackAddressInformation(uptr addr, uptr access_size,
146                                StackAddressDescription *descr);
147
148struct GlobalAddressDescription {
149  uptr addr;
150  // Assume address is close to at most four globals.
151  static const int kMaxGlobals = 4;
152  __asan_global globals[kMaxGlobals];
153  u32 reg_sites[kMaxGlobals];
154  uptr access_size;
155  u8 size;
156
157  void Print(const char *bug_type = "") const;
158
159  // Returns true when this descriptions points inside the same global variable
160  // as other. Descriptions can have different address within the variable
161  bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const;
162};
163
164bool GetGlobalAddressInformation(uptr addr, uptr access_size,
165                                 GlobalAddressDescription *descr);
166bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
167
168// General function to describe an address. Will try to describe the address as
169// a shadow, global (variable), stack, or heap address.
170// bug_type is optional and is used for checking if we're reporting an
171// initialization-order-fiasco
172// The proper access_size should be passed for stack, global, and heap
173// addresses. Defaults to 1.
174// Each of the *AddressDescription functions has its own Print() member, which
175// may take access_size and bug_type parameters if needed.
176void PrintAddressDescription(uptr addr, uptr access_size = 1,
177                             const char *bug_type = "");
178
179enum AddressKind {
180  kAddressKindWild,
181  kAddressKindShadow,
182  kAddressKindHeap,
183  kAddressKindStack,
184  kAddressKindGlobal,
185};
186
187class AddressDescription {
188  struct AddressDescriptionData {
189    AddressKind kind;
190    union {
191      ShadowAddressDescription shadow;
192      HeapAddressDescription heap;
193      StackAddressDescription stack;
194      GlobalAddressDescription global;
195      uptr addr;
196    };
197  };
198
199  AddressDescriptionData data;
200
201 public:
202  AddressDescription() = default;
203  // shouldLockThreadRegistry allows us to skip locking if we're sure we already
204  // have done it.
205  AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
206      : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
207  AddressDescription(uptr addr, uptr access_size,
208                     bool shouldLockThreadRegistry = true);
209
210  uptr Address() const {
211    switch (data.kind) {
212      case kAddressKindWild:
213        return data.addr;
214      case kAddressKindShadow:
215        return data.shadow.addr;
216      case kAddressKindHeap:
217        return data.heap.addr;
218      case kAddressKindStack:
219        return data.stack.addr;
220      case kAddressKindGlobal:
221        return data.global.addr;
222    }
223    UNREACHABLE("AddressInformation kind is invalid");
224  }
225  void Print(const char *bug_descr = nullptr) const {
226    switch (data.kind) {
227      case kAddressKindWild:
228        Printf("Address %p is a wild pointer.\n", data.addr);
229        return;
230      case kAddressKindShadow:
231        return data.shadow.Print();
232      case kAddressKindHeap:
233        return data.heap.Print();
234      case kAddressKindStack:
235        return data.stack.Print();
236      case kAddressKindGlobal:
237        // initialization-order-fiasco has a special Print()
238        return data.global.Print(bug_descr);
239    }
240    UNREACHABLE("AddressInformation kind is invalid");
241  }
242
243  void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
244
245  const ShadowAddressDescription *AsShadow() const {
246    return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
247  }
248  const HeapAddressDescription *AsHeap() const {
249    return data.kind == kAddressKindHeap ? &data.heap : nullptr;
250  }
251  const StackAddressDescription *AsStack() const {
252    return data.kind == kAddressKindStack ? &data.stack : nullptr;
253  }
254  const GlobalAddressDescription *AsGlobal() const {
255    return data.kind == kAddressKindGlobal ? &data.global : nullptr;
256  }
257};
258
259}  // namespace __asan
260
261#endif  // ASAN_DESCRIPTIONS_H
262