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