123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- //===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file is a part of AddressSanitizer, an address sanity checker.
- //
- // ASan-private header for asan_descriptions.cpp.
- // TODO(filcab): Most struct definitions should move to the interface headers.
- //===----------------------------------------------------------------------===//
- #ifndef ASAN_DESCRIPTIONS_H
- #define ASAN_DESCRIPTIONS_H
- #include "asan_allocator.h"
- #include "asan_thread.h"
- #include "sanitizer_common/sanitizer_common.h"
- #include "sanitizer_common/sanitizer_report_decorator.h"
- namespace __asan {
- void DescribeThread(AsanThreadContext *context);
- static inline void DescribeThread(AsanThread *t) {
- if (t) DescribeThread(t->context());
- }
- class AsanThreadIdAndName {
- public:
- explicit AsanThreadIdAndName(AsanThreadContext *t);
- explicit AsanThreadIdAndName(u32 tid);
- // Contains "T%tid (%name)" or "T%tid" if the name is empty.
- const char *c_str() const { return &name[0]; }
- private:
- void Init(u32 tid, const char *tname);
- char name[128];
- };
- class Decorator : public __sanitizer::SanitizerCommonDecorator {
- public:
- Decorator() : SanitizerCommonDecorator() {}
- const char *Access() { return Blue(); }
- const char *Location() { return Green(); }
- const char *Allocation() { return Magenta(); }
- const char *ShadowByte(u8 byte) {
- switch (byte) {
- case kAsanHeapLeftRedzoneMagic:
- case kAsanArrayCookieMagic:
- return Red();
- case kAsanHeapFreeMagic:
- return Magenta();
- case kAsanStackLeftRedzoneMagic:
- case kAsanStackMidRedzoneMagic:
- case kAsanStackRightRedzoneMagic:
- return Red();
- case kAsanStackAfterReturnMagic:
- return Magenta();
- case kAsanInitializationOrderMagic:
- return Cyan();
- case kAsanUserPoisonedMemoryMagic:
- case kAsanContiguousContainerOOBMagic:
- case kAsanAllocaLeftMagic:
- case kAsanAllocaRightMagic:
- return Blue();
- case kAsanStackUseAfterScopeMagic:
- return Magenta();
- case kAsanGlobalRedzoneMagic:
- return Red();
- case kAsanInternalHeapMagic:
- return Yellow();
- case kAsanIntraObjectRedzone:
- return Yellow();
- default:
- return Default();
- }
- }
- };
- enum ShadowKind : u8 {
- kShadowKindLow,
- kShadowKindGap,
- kShadowKindHigh,
- };
- static const char *const ShadowNames[] = {"low shadow", "shadow gap",
- "high shadow"};
- struct ShadowAddressDescription {
- uptr addr;
- ShadowKind kind;
- u8 shadow_byte;
- void Print() const;
- };
- bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
- bool DescribeAddressIfShadow(uptr addr);
- enum AccessType {
- kAccessTypeLeft,
- kAccessTypeRight,
- kAccessTypeInside,
- kAccessTypeUnknown, // This means we have an AddressSanitizer bug!
- };
- struct ChunkAccess {
- uptr bad_addr;
- sptr offset;
- uptr chunk_begin;
- uptr chunk_size;
- u32 user_requested_alignment : 12;
- u32 access_type : 2;
- u32 alloc_type : 2;
- };
- struct HeapAddressDescription {
- uptr addr;
- uptr alloc_tid;
- uptr free_tid;
- u32 alloc_stack_id;
- u32 free_stack_id;
- ChunkAccess chunk_access;
- void Print() const;
- };
- bool GetHeapAddressInformation(uptr addr, uptr access_size,
- HeapAddressDescription *descr);
- bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
- struct StackAddressDescription {
- uptr addr;
- uptr tid;
- uptr offset;
- uptr frame_pc;
- uptr access_size;
- const char *frame_descr;
- void Print() const;
- };
- bool GetStackAddressInformation(uptr addr, uptr access_size,
- StackAddressDescription *descr);
- struct WildAddressDescription {
- uptr addr;
- uptr access_size;
- void Print() const;
- };
- struct GlobalAddressDescription {
- uptr addr;
- // Assume address is close to at most four globals.
- static const int kMaxGlobals = 4;
- __asan_global globals[kMaxGlobals];
- u32 reg_sites[kMaxGlobals];
- uptr access_size;
- u8 size;
- void Print(const char *bug_type = "") const;
- // Returns true when this descriptions points inside the same global variable
- // as other. Descriptions can have different address within the variable
- bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const;
- };
- bool GetGlobalAddressInformation(uptr addr, uptr access_size,
- GlobalAddressDescription *descr);
- bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
- // General function to describe an address. Will try to describe the address as
- // a shadow, global (variable), stack, or heap address.
- // bug_type is optional and is used for checking if we're reporting an
- // initialization-order-fiasco
- // The proper access_size should be passed for stack, global, and heap
- // addresses. Defaults to 1.
- // Each of the *AddressDescription functions has its own Print() member, which
- // may take access_size and bug_type parameters if needed.
- void PrintAddressDescription(uptr addr, uptr access_size = 1,
- const char *bug_type = "");
- enum AddressKind {
- kAddressKindWild,
- kAddressKindShadow,
- kAddressKindHeap,
- kAddressKindStack,
- kAddressKindGlobal,
- };
- class AddressDescription {
- struct AddressDescriptionData {
- AddressKind kind;
- union {
- ShadowAddressDescription shadow;
- HeapAddressDescription heap;
- StackAddressDescription stack;
- GlobalAddressDescription global;
- WildAddressDescription wild;
- };
- };
- AddressDescriptionData data;
- public:
- AddressDescription() = default;
- // shouldLockThreadRegistry allows us to skip locking if we're sure we already
- // have done it.
- explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
- : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
- AddressDescription(uptr addr, uptr access_size,
- bool shouldLockThreadRegistry = true);
- uptr Address() const {
- switch (data.kind) {
- case kAddressKindWild:
- return data.wild.addr;
- case kAddressKindShadow:
- return data.shadow.addr;
- case kAddressKindHeap:
- return data.heap.addr;
- case kAddressKindStack:
- return data.stack.addr;
- case kAddressKindGlobal:
- return data.global.addr;
- }
- UNREACHABLE("AddressInformation kind is invalid");
- }
- void Print(const char *bug_descr = nullptr) const {
- switch (data.kind) {
- case kAddressKindWild:
- data.wild.Print();
- return;
- case kAddressKindShadow:
- return data.shadow.Print();
- case kAddressKindHeap:
- return data.heap.Print();
- case kAddressKindStack:
- return data.stack.Print();
- case kAddressKindGlobal:
- // initialization-order-fiasco has a special Print()
- return data.global.Print(bug_descr);
- }
- UNREACHABLE("AddressInformation kind is invalid");
- }
- void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
- const ShadowAddressDescription *AsShadow() const {
- return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
- }
- const HeapAddressDescription *AsHeap() const {
- return data.kind == kAddressKindHeap ? &data.heap : nullptr;
- }
- const StackAddressDescription *AsStack() const {
- return data.kind == kAddressKindStack ? &data.stack : nullptr;
- }
- const GlobalAddressDescription *AsGlobal() const {
- return data.kind == kAddressKindGlobal ? &data.global : nullptr;
- }
- };
- } // namespace __asan
- #endif // ASAN_DESCRIPTIONS_H
|