1311120Sdim//===-- asan_descriptions.h -------------------------------------*- C++ -*-===// 2311120Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6311120Sdim// 7311120Sdim//===----------------------------------------------------------------------===// 8311120Sdim// 9311120Sdim// This file is a part of AddressSanitizer, an address sanity checker. 10311120Sdim// 11360784Sdim// ASan-private header for asan_descriptions.cpp. 12311120Sdim// TODO(filcab): Most struct definitions should move to the interface headers. 13311120Sdim//===----------------------------------------------------------------------===// 14311120Sdim#ifndef ASAN_DESCRIPTIONS_H 15311120Sdim#define ASAN_DESCRIPTIONS_H 16311120Sdim 17311120Sdim#include "asan_allocator.h" 18311120Sdim#include "asan_thread.h" 19311120Sdim#include "sanitizer_common/sanitizer_common.h" 20311120Sdim#include "sanitizer_common/sanitizer_report_decorator.h" 21311120Sdim 22311120Sdimnamespace __asan { 23311120Sdim 24311120Sdimvoid DescribeThread(AsanThreadContext *context); 25311120Sdimstatic inline void DescribeThread(AsanThread *t) { 26311120Sdim if (t) DescribeThread(t->context()); 27311120Sdim} 28311120Sdim 29341825Sdimclass AsanThreadIdAndName { 30341825Sdim public: 31341825Sdim explicit AsanThreadIdAndName(AsanThreadContext *t); 32341825Sdim explicit AsanThreadIdAndName(u32 tid); 33341825Sdim 34341825Sdim // Contains "T%tid (%name)" or "T%tid" if the name is empty. 35341825Sdim const char *c_str() const { return &name[0]; } 36341825Sdim 37341825Sdim private: 38341825Sdim void Init(u32 tid, const char *tname); 39341825Sdim 40341825Sdim char name[128]; 41341825Sdim}; 42341825Sdim 43311120Sdimclass Decorator : public __sanitizer::SanitizerCommonDecorator { 44311120Sdim public: 45311120Sdim Decorator() : SanitizerCommonDecorator() {} 46311120Sdim const char *Access() { return Blue(); } 47311120Sdim const char *Location() { return Green(); } 48311120Sdim const char *Allocation() { return Magenta(); } 49311120Sdim 50311120Sdim const char *ShadowByte(u8 byte) { 51311120Sdim switch (byte) { 52311120Sdim case kAsanHeapLeftRedzoneMagic: 53311120Sdim case kAsanArrayCookieMagic: 54311120Sdim return Red(); 55311120Sdim case kAsanHeapFreeMagic: 56311120Sdim return Magenta(); 57311120Sdim case kAsanStackLeftRedzoneMagic: 58311120Sdim case kAsanStackMidRedzoneMagic: 59311120Sdim case kAsanStackRightRedzoneMagic: 60311120Sdim return Red(); 61311120Sdim case kAsanStackAfterReturnMagic: 62311120Sdim return Magenta(); 63311120Sdim case kAsanInitializationOrderMagic: 64311120Sdim return Cyan(); 65311120Sdim case kAsanUserPoisonedMemoryMagic: 66311120Sdim case kAsanContiguousContainerOOBMagic: 67311120Sdim case kAsanAllocaLeftMagic: 68311120Sdim case kAsanAllocaRightMagic: 69311120Sdim return Blue(); 70311120Sdim case kAsanStackUseAfterScopeMagic: 71311120Sdim return Magenta(); 72311120Sdim case kAsanGlobalRedzoneMagic: 73311120Sdim return Red(); 74311120Sdim case kAsanInternalHeapMagic: 75311120Sdim return Yellow(); 76311120Sdim case kAsanIntraObjectRedzone: 77311120Sdim return Yellow(); 78311120Sdim default: 79311120Sdim return Default(); 80311120Sdim } 81311120Sdim } 82311120Sdim}; 83311120Sdim 84311120Sdimenum ShadowKind : u8 { 85311120Sdim kShadowKindLow, 86311120Sdim kShadowKindGap, 87311120Sdim kShadowKindHigh, 88311120Sdim}; 89311120Sdimstatic const char *const ShadowNames[] = {"low shadow", "shadow gap", 90311120Sdim "high shadow"}; 91311120Sdim 92311120Sdimstruct ShadowAddressDescription { 93311120Sdim uptr addr; 94311120Sdim ShadowKind kind; 95311120Sdim u8 shadow_byte; 96311120Sdim 97311120Sdim void Print() const; 98311120Sdim}; 99311120Sdim 100311120Sdimbool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr); 101311120Sdimbool DescribeAddressIfShadow(uptr addr); 102311120Sdim 103311120Sdimenum AccessType { 104311120Sdim kAccessTypeLeft, 105311120Sdim kAccessTypeRight, 106311120Sdim kAccessTypeInside, 107311120Sdim kAccessTypeUnknown, // This means we have an AddressSanitizer bug! 108311120Sdim}; 109311120Sdim 110311120Sdimstruct ChunkAccess { 111311120Sdim uptr bad_addr; 112311120Sdim sptr offset; 113311120Sdim uptr chunk_begin; 114311120Sdim uptr chunk_size; 115327952Sdim u32 user_requested_alignment : 12; 116311120Sdim u32 access_type : 2; 117311120Sdim u32 alloc_type : 2; 118311120Sdim}; 119311120Sdim 120311120Sdimstruct HeapAddressDescription { 121311120Sdim uptr addr; 122311120Sdim uptr alloc_tid; 123311120Sdim uptr free_tid; 124311120Sdim u32 alloc_stack_id; 125311120Sdim u32 free_stack_id; 126311120Sdim ChunkAccess chunk_access; 127311120Sdim 128311120Sdim void Print() const; 129311120Sdim}; 130311120Sdim 131311120Sdimbool GetHeapAddressInformation(uptr addr, uptr access_size, 132311120Sdim HeapAddressDescription *descr); 133311120Sdimbool DescribeAddressIfHeap(uptr addr, uptr access_size = 1); 134311120Sdim 135311120Sdimstruct StackAddressDescription { 136311120Sdim uptr addr; 137311120Sdim uptr tid; 138311120Sdim uptr offset; 139311120Sdim uptr frame_pc; 140311120Sdim uptr access_size; 141311120Sdim const char *frame_descr; 142311120Sdim 143311120Sdim void Print() const; 144311120Sdim}; 145311120Sdim 146311120Sdimbool GetStackAddressInformation(uptr addr, uptr access_size, 147311120Sdim StackAddressDescription *descr); 148311120Sdim 149311120Sdimstruct GlobalAddressDescription { 150311120Sdim uptr addr; 151311120Sdim // Assume address is close to at most four globals. 152311120Sdim static const int kMaxGlobals = 4; 153311120Sdim __asan_global globals[kMaxGlobals]; 154311120Sdim u32 reg_sites[kMaxGlobals]; 155311120Sdim uptr access_size; 156311120Sdim u8 size; 157311120Sdim 158311120Sdim void Print(const char *bug_type = "") const; 159327952Sdim 160327952Sdim // Returns true when this descriptions points inside the same global variable 161327952Sdim // as other. Descriptions can have different address within the variable 162327952Sdim bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const; 163311120Sdim}; 164311120Sdim 165311120Sdimbool GetGlobalAddressInformation(uptr addr, uptr access_size, 166311120Sdim GlobalAddressDescription *descr); 167311120Sdimbool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type); 168311120Sdim 169311120Sdim// General function to describe an address. Will try to describe the address as 170311120Sdim// a shadow, global (variable), stack, or heap address. 171311120Sdim// bug_type is optional and is used for checking if we're reporting an 172311120Sdim// initialization-order-fiasco 173311120Sdim// The proper access_size should be passed for stack, global, and heap 174311120Sdim// addresses. Defaults to 1. 175311120Sdim// Each of the *AddressDescription functions has its own Print() member, which 176311120Sdim// may take access_size and bug_type parameters if needed. 177311120Sdimvoid PrintAddressDescription(uptr addr, uptr access_size = 1, 178311120Sdim const char *bug_type = ""); 179311120Sdim 180311120Sdimenum AddressKind { 181311120Sdim kAddressKindWild, 182311120Sdim kAddressKindShadow, 183311120Sdim kAddressKindHeap, 184311120Sdim kAddressKindStack, 185311120Sdim kAddressKindGlobal, 186311120Sdim}; 187311120Sdim 188311120Sdimclass AddressDescription { 189311120Sdim struct AddressDescriptionData { 190311120Sdim AddressKind kind; 191311120Sdim union { 192311120Sdim ShadowAddressDescription shadow; 193311120Sdim HeapAddressDescription heap; 194311120Sdim StackAddressDescription stack; 195311120Sdim GlobalAddressDescription global; 196311120Sdim uptr addr; 197311120Sdim }; 198311120Sdim }; 199311120Sdim 200311120Sdim AddressDescriptionData data; 201311120Sdim 202311120Sdim public: 203311120Sdim AddressDescription() = default; 204311120Sdim // shouldLockThreadRegistry allows us to skip locking if we're sure we already 205311120Sdim // have done it. 206360784Sdim explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true) 207311120Sdim : AddressDescription(addr, 1, shouldLockThreadRegistry) {} 208311120Sdim AddressDescription(uptr addr, uptr access_size, 209311120Sdim bool shouldLockThreadRegistry = true); 210311120Sdim 211311120Sdim uptr Address() const { 212311120Sdim switch (data.kind) { 213311120Sdim case kAddressKindWild: 214311120Sdim return data.addr; 215311120Sdim case kAddressKindShadow: 216311120Sdim return data.shadow.addr; 217311120Sdim case kAddressKindHeap: 218311120Sdim return data.heap.addr; 219311120Sdim case kAddressKindStack: 220311120Sdim return data.stack.addr; 221311120Sdim case kAddressKindGlobal: 222311120Sdim return data.global.addr; 223311120Sdim } 224311120Sdim UNREACHABLE("AddressInformation kind is invalid"); 225311120Sdim } 226311120Sdim void Print(const char *bug_descr = nullptr) const { 227311120Sdim switch (data.kind) { 228311120Sdim case kAddressKindWild: 229311120Sdim Printf("Address %p is a wild pointer.\n", data.addr); 230311120Sdim return; 231311120Sdim case kAddressKindShadow: 232311120Sdim return data.shadow.Print(); 233311120Sdim case kAddressKindHeap: 234311120Sdim return data.heap.Print(); 235311120Sdim case kAddressKindStack: 236311120Sdim return data.stack.Print(); 237311120Sdim case kAddressKindGlobal: 238311120Sdim // initialization-order-fiasco has a special Print() 239311120Sdim return data.global.Print(bug_descr); 240311120Sdim } 241311120Sdim UNREACHABLE("AddressInformation kind is invalid"); 242311120Sdim } 243311120Sdim 244311120Sdim void StoreTo(AddressDescriptionData *dst) const { *dst = data; } 245311120Sdim 246311120Sdim const ShadowAddressDescription *AsShadow() const { 247311120Sdim return data.kind == kAddressKindShadow ? &data.shadow : nullptr; 248311120Sdim } 249311120Sdim const HeapAddressDescription *AsHeap() const { 250311120Sdim return data.kind == kAddressKindHeap ? &data.heap : nullptr; 251311120Sdim } 252311120Sdim const StackAddressDescription *AsStack() const { 253311120Sdim return data.kind == kAddressKindStack ? &data.stack : nullptr; 254311120Sdim } 255311120Sdim const GlobalAddressDescription *AsGlobal() const { 256311120Sdim return data.kind == kAddressKindGlobal ? &data.global : nullptr; 257311120Sdim } 258311120Sdim}; 259311120Sdim 260311120Sdim} // namespace __asan 261311120Sdim 262311120Sdim#endif // ASAN_DESCRIPTIONS_H 263