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