Path: blob/main/contrib/llvm-project/compiler-rt/lib/asan/asan_descriptions.h
35233 views
//===-- asan_descriptions.h -------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of AddressSanitizer, an address sanity checker.9//10// ASan-private header for asan_descriptions.cpp.11// TODO(filcab): Most struct definitions should move to the interface headers.12//===----------------------------------------------------------------------===//13#ifndef ASAN_DESCRIPTIONS_H14#define ASAN_DESCRIPTIONS_H1516#include "asan_allocator.h"17#include "asan_thread.h"18#include "sanitizer_common/sanitizer_common.h"19#include "sanitizer_common/sanitizer_report_decorator.h"2021namespace __asan {2223void DescribeThread(AsanThreadContext *context);24static inline void DescribeThread(AsanThread *t) {25if (t) DescribeThread(t->context());26}2728class AsanThreadIdAndName {29public:30explicit AsanThreadIdAndName(AsanThreadContext *t);31explicit AsanThreadIdAndName(u32 tid);3233// Contains "T%tid (%name)" or "T%tid" if the name is empty.34const char *c_str() const { return &name[0]; }3536private:37void Init(u32 tid, const char *tname);3839char name[128];40};4142class Decorator : public __sanitizer::SanitizerCommonDecorator {43public:44Decorator() : SanitizerCommonDecorator() {}45const char *Access() { return Blue(); }46const char *Location() { return Green(); }47const char *Allocation() { return Magenta(); }4849const char *ShadowByte(u8 byte) {50switch (byte) {51case kAsanHeapLeftRedzoneMagic:52case kAsanArrayCookieMagic:53return Red();54case kAsanHeapFreeMagic:55return Magenta();56case kAsanStackLeftRedzoneMagic:57case kAsanStackMidRedzoneMagic:58case kAsanStackRightRedzoneMagic:59return Red();60case kAsanStackAfterReturnMagic:61return Magenta();62case kAsanInitializationOrderMagic:63return Cyan();64case kAsanUserPoisonedMemoryMagic:65case kAsanContiguousContainerOOBMagic:66case kAsanAllocaLeftMagic:67case kAsanAllocaRightMagic:68return Blue();69case kAsanStackUseAfterScopeMagic:70return Magenta();71case kAsanGlobalRedzoneMagic:72return Red();73case kAsanInternalHeapMagic:74return Yellow();75case kAsanIntraObjectRedzone:76return Yellow();77default:78return Default();79}80}81};8283enum ShadowKind : u8 {84kShadowKindLow,85kShadowKindGap,86kShadowKindHigh,87};88static const char *const ShadowNames[] = {"low shadow", "shadow gap",89"high shadow"};9091struct ShadowAddressDescription {92uptr addr;93ShadowKind kind;94u8 shadow_byte;9596void Print() const;97};9899bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);100bool DescribeAddressIfShadow(uptr addr);101102enum AccessType {103kAccessTypeLeft,104kAccessTypeRight,105kAccessTypeInside,106kAccessTypeUnknown, // This means we have an AddressSanitizer bug!107};108109struct ChunkAccess {110uptr bad_addr;111sptr offset;112uptr chunk_begin;113uptr chunk_size;114u32 user_requested_alignment : 12;115u32 access_type : 2;116u32 alloc_type : 2;117};118119struct HeapAddressDescription {120uptr addr;121uptr alloc_tid;122uptr free_tid;123u32 alloc_stack_id;124u32 free_stack_id;125ChunkAccess chunk_access;126127void Print() const;128};129130bool GetHeapAddressInformation(uptr addr, uptr access_size,131HeapAddressDescription *descr);132bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);133134struct StackAddressDescription {135uptr addr;136uptr tid;137uptr offset;138uptr frame_pc;139uptr access_size;140const char *frame_descr;141142void Print() const;143};144145bool GetStackAddressInformation(uptr addr, uptr access_size,146StackAddressDescription *descr);147148struct WildAddressDescription {149uptr addr;150uptr access_size;151152void Print() const;153};154155struct GlobalAddressDescription {156uptr addr;157// Assume address is close to at most four globals.158static const int kMaxGlobals = 4;159__asan_global globals[kMaxGlobals];160u32 reg_sites[kMaxGlobals];161uptr access_size;162u8 size;163164void Print(const char *bug_type = "") const;165166// Returns true when this descriptions points inside the same global variable167// as other. Descriptions can have different address within the variable168bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const;169};170171bool GetGlobalAddressInformation(uptr addr, uptr access_size,172GlobalAddressDescription *descr);173bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);174175// General function to describe an address. Will try to describe the address as176// a shadow, global (variable), stack, or heap address.177// bug_type is optional and is used for checking if we're reporting an178// initialization-order-fiasco179// The proper access_size should be passed for stack, global, and heap180// addresses. Defaults to 1.181// Each of the *AddressDescription functions has its own Print() member, which182// may take access_size and bug_type parameters if needed.183void PrintAddressDescription(uptr addr, uptr access_size = 1,184const char *bug_type = "");185186enum AddressKind {187kAddressKindWild,188kAddressKindShadow,189kAddressKindHeap,190kAddressKindStack,191kAddressKindGlobal,192};193194class AddressDescription {195struct AddressDescriptionData {196AddressKind kind;197union {198ShadowAddressDescription shadow;199HeapAddressDescription heap;200StackAddressDescription stack;201GlobalAddressDescription global;202WildAddressDescription wild;203};204};205206AddressDescriptionData data;207208public:209AddressDescription() = default;210// shouldLockThreadRegistry allows us to skip locking if we're sure we already211// have done it.212explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)213: AddressDescription(addr, 1, shouldLockThreadRegistry) {}214AddressDescription(uptr addr, uptr access_size,215bool shouldLockThreadRegistry = true);216217uptr Address() const {218switch (data.kind) {219case kAddressKindWild:220return data.wild.addr;221case kAddressKindShadow:222return data.shadow.addr;223case kAddressKindHeap:224return data.heap.addr;225case kAddressKindStack:226return data.stack.addr;227case kAddressKindGlobal:228return data.global.addr;229}230UNREACHABLE("AddressInformation kind is invalid");231}232void Print(const char *bug_descr = nullptr) const {233switch (data.kind) {234case kAddressKindWild:235data.wild.Print();236return;237case kAddressKindShadow:238return data.shadow.Print();239case kAddressKindHeap:240return data.heap.Print();241case kAddressKindStack:242return data.stack.Print();243case kAddressKindGlobal:244// initialization-order-fiasco has a special Print()245return data.global.Print(bug_descr);246}247UNREACHABLE("AddressInformation kind is invalid");248}249250void StoreTo(AddressDescriptionData *dst) const { *dst = data; }251252const ShadowAddressDescription *AsShadow() const {253return data.kind == kAddressKindShadow ? &data.shadow : nullptr;254}255const HeapAddressDescription *AsHeap() const {256return data.kind == kAddressKindHeap ? &data.heap : nullptr;257}258const StackAddressDescription *AsStack() const {259return data.kind == kAddressKindStack ? &data.stack : nullptr;260}261const GlobalAddressDescription *AsGlobal() const {262return data.kind == kAddressKindGlobal ? &data.global : nullptr;263}264};265266} // namespace __asan267268#endif // ASAN_DESCRIPTIONS_H269270271