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