blob: 1de6eb175f02c628d0f33930341b5f945283fa37 [file] [log] [blame]
Kostya Serebryany1e172b42011-11-30 01:07:02 +00001//===-- asan_internal.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 which defines various general utilities.
13//===----------------------------------------------------------------------===//
14#ifndef ASAN_INTERNAL_H
15#define ASAN_INTERNAL_H
16
17#include <stdint.h> // for __WORDSIZE
18#include <stdlib.h> // for size_t
19#include <unistd.h> // for _exit
20
21#ifdef ANDROID
22#include <sys/atomics.h>
23#endif
24
25#ifdef ADDRESS_SANITIZER
26# error "The AddressSanitizer run-time should not be"
27 " instrumented by AddressSanitizer"
28#endif
29
30// All internal functions in asan reside inside the __asan namespace
31// to avoid namespace collisions with the user programs.
32// Seperate namespace also makes it simpler to distinguish the asan run-time
33// functions from the instrumented user code in a profile.
34namespace __asan {
35
36class AsanThread;
37struct AsanStackTrace;
38
39// asan_rtl.cc
40void CheckFailed(const char *cond, const char *file, int line);
41void ShowStatsAndAbort();
42
43// asan_globals.cc
44bool DescribeAddrIfGlobal(uintptr_t addr);
45
46// asan_malloc_linux.cc / asan_malloc_mac.cc
47void ReplaceSystemMalloc();
48
49// asan_linux.cc / asan_mac.cc
50void *AsanDoesNotSupportStaticLinkage();
51void *asan_mmap(void *addr, size_t length, int prot, int flags,
52 int fd, uint64_t offset);
53ssize_t asan_write(int fd, const void *buf, size_t count);
54
55// asan_printf.cc
56void RawWrite(const char *buffer);
57int SNPrint(char *buffer, size_t length, const char *format, ...);
58void Printf(const char *format, ...);
59void Report(const char *format, ...);
60
61extern size_t FLAG_quarantine_size;
62extern int FLAG_demangle;
63extern bool FLAG_symbolize;
64extern int FLAG_v;
65extern bool FLAG_mt;
66extern size_t FLAG_redzone;
67extern int FLAG_debug;
68extern bool FLAG_poison_shadow;
69extern int FLAG_report_globals;
70extern size_t FLAG_malloc_context_size;
71extern bool FLAG_stats;
72extern bool FLAG_replace_str;
73extern bool FLAG_replace_intrin;
74extern bool FLAG_replace_cfallocator;
75extern bool FLAG_fast_unwind;
76extern bool FLAG_use_fake_stack;
77extern size_t FLAG_max_malloc_fill_size;
78extern int FLAG_exitcode;
79extern bool FLAG_allow_user_poisoning;
80
81extern int asan_inited;
82// Used to avoid infinite recursion in __asan_init().
83extern bool asan_init_is_running;
84
85enum LinkerInitialized { LINKER_INITIALIZED = 0 };
86
87#ifndef ASAN_DIE
88#define ASAN_DIE _exit(FLAG_exitcode)
89#endif // ASAN_DIE
90
91#define CHECK(cond) do { if (!(cond)) { \
92 CheckFailed(#cond, __FILE__, __LINE__); \
93}}while(0)
94
95#define RAW_CHECK_MSG(expr, msg) do { \
96 if (!(expr)) { \
97 RawWrite(msg); \
98 ASAN_DIE; \
99 } \
100} while (0)
101
102#define RAW_CHECK(expr) RAW_CHECK_MSG(expr, #expr)
103
104#define UNIMPLEMENTED() CHECK("unimplemented" && 0)
105
106#define ASAN_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
107
108const size_t kWordSize = __WORDSIZE / 8;
109const size_t kWordSizeInBits = 8 * kWordSize;
110const size_t kPageSizeBits = 12;
111const size_t kPageSize = 1UL << kPageSizeBits;
112
113#define GET_CALLER_PC() (uintptr_t)__builtin_return_address(0)
114#define GET_CURRENT_FRAME() (uintptr_t)__builtin_frame_address(0)
115
116#define GET_BP_PC_SP \
117 uintptr_t bp = GET_CURRENT_FRAME(); \
118 uintptr_t pc = GET_CALLER_PC(); \
119 uintptr_t local_stack; \
120 uintptr_t sp = (uintptr_t)&local_stack;
121
122// These magic values are written to shadow for better error reporting.
123const int kAsanHeapLeftRedzoneMagic = 0xfa;
124const int kAsanHeapRightRedzoneMagic = 0xfb;
125const int kAsanHeapFreeMagic = 0xfd;
126const int kAsanStackLeftRedzoneMagic = 0xf1;
127const int kAsanStackMidRedzoneMagic = 0xf2;
128const int kAsanStackRightRedzoneMagic = 0xf3;
129const int kAsanStackPartialRedzoneMagic = 0xf4;
130const int kAsanStackAfterReturnMagic = 0xf5;
131const int kAsanUserPoisonedMemoryMagic = 0xf7;
132const int kAsanGlobalRedzoneMagic = 0xf9;
133
134static const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3;
135static const uintptr_t kRetiredStackFrameMagic = 0x45E0360E;
136
137// Poison the shadow memory which corresponds to 'redzone_size' bytes
138// of the original memory, where first 'size' bytes are addressable.
139static inline void
140PoisonShadowPartialRightRedzone(unsigned char *shadow,
141 uintptr_t size,
142 uintptr_t redzone_size,
143 uintptr_t shadow_granularity,
144 unsigned char magic) {
145 for (uintptr_t i = 0; i < redzone_size;
146 i+= shadow_granularity, shadow++) {
147 if (i + shadow_granularity <= size) {
148 *shadow = 0; // fully addressable
149 } else if (i >= size) {
150 *shadow = (shadow_granularity == 128) ? 0xff : magic; // unaddressable
151 } else {
152 *shadow = size - i; // first size-i bytes are addressable
153 }
154 }
155}
156
157// -------------------------- Atomic ---------------- {{{1
158static inline int AtomicInc(int *a) {
159 if (!FLAG_mt) return ++(*a);
160#ifdef ANDROID
161 return __atomic_inc(a) + 1;
162#else
163 return __sync_add_and_fetch(a, 1);
164#endif
165}
166
167static inline int AtomicDec(int *a) {
168 if (!FLAG_mt) return --(*a);
169#ifdef ANDROID
170 return __atomic_dec(a) - 1;
171#else
172 return __sync_add_and_fetch(a, -1);
173#endif
174}
175
176} // namespace __asan
177
178#endif // ASAN_INTERNAL_H