asan_globals.cc revision e4bfca2b154a6ab4eda921aff454035f33f3551a
1//===-- asan_globals.cc ---------------------------------------------------===// 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// Handle globals. 13//===----------------------------------------------------------------------===// 14#include "asan_interceptors.h" 15#include "asan_interface.h" 16#include "asan_internal.h" 17#include "asan_lock.h" 18#include "asan_mapping.h" 19#include "asan_report.h" 20#include "asan_stack.h" 21#include "asan_stats.h" 22#include "asan_thread.h" 23 24namespace __asan { 25 26typedef __asan_global Global; 27 28struct ListOfGlobals { 29 const Global *g; 30 ListOfGlobals *next; 31}; 32 33static AsanLock mu_for_globals(LINKER_INITIALIZED); 34static ListOfGlobals *list_of_globals; 35static LowLevelAllocator allocator_for_globals(LINKER_INITIALIZED); 36 37void PoisonRedZones(const Global &g) { 38 uptr shadow_rz_size = kGlobalAndStackRedzone >> SHADOW_SCALE; 39 CHECK(shadow_rz_size == 1 || shadow_rz_size == 2 || shadow_rz_size == 4); 40 // full right redzone 41 uptr g_aligned_size = kGlobalAndStackRedzone * 42 ((g.size + kGlobalAndStackRedzone - 1) / kGlobalAndStackRedzone); 43 PoisonShadow(g.beg + g_aligned_size, 44 kGlobalAndStackRedzone, kAsanGlobalRedzoneMagic); 45 if ((g.size % kGlobalAndStackRedzone) != 0) { 46 // partial right redzone 47 u64 g_aligned_down_size = kGlobalAndStackRedzone * 48 (g.size / kGlobalAndStackRedzone); 49 CHECK(g_aligned_down_size == g_aligned_size - kGlobalAndStackRedzone); 50 PoisonShadowPartialRightRedzone(g.beg + g_aligned_down_size, 51 g.size % kGlobalAndStackRedzone, 52 kGlobalAndStackRedzone, 53 kAsanGlobalRedzoneMagic); 54 } 55} 56 57static uptr GetAlignedSize(uptr size) { 58 return ((size + kGlobalAndStackRedzone - 1) / kGlobalAndStackRedzone) 59 * kGlobalAndStackRedzone; 60} 61 62bool DescribeAddressIfGlobal(uptr addr) { 63 if (!flags()->report_globals) return false; 64 ScopedLock lock(&mu_for_globals); 65 bool res = false; 66 for (ListOfGlobals *l = list_of_globals; l; l = l->next) { 67 const Global &g = *l->g; 68 if (flags()->report_globals >= 2) 69 Report("Search Global: beg=%p size=%zu name=%s\n", 70 (void*)g.beg, g.size, (char*)g.name); 71 res |= DescribeAddressRelativeToGlobal(addr, g); 72 } 73 return res; 74} 75 76// Register a global variable. 77// This function may be called more than once for every global 78// so we store the globals in a map. 79static void RegisterGlobal(const Global *g) { 80 CHECK(asan_inited); 81 CHECK(flags()->report_globals); 82 CHECK(AddrIsInMem(g->beg)); 83 CHECK(AddrIsAlignedByGranularity(g->beg)); 84 CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); 85 PoisonRedZones(*g); 86 ListOfGlobals *l = 87 (ListOfGlobals*)allocator_for_globals.Allocate(sizeof(ListOfGlobals)); 88 l->g = g; 89 l->next = list_of_globals; 90 list_of_globals = l; 91 if (flags()->report_globals >= 2) 92 Report("Added Global: beg=%p size=%zu name=%s\n", 93 (void*)g->beg, g->size, g->name); 94} 95 96static void UnregisterGlobal(const Global *g) { 97 CHECK(asan_inited); 98 CHECK(flags()->report_globals); 99 CHECK(AddrIsInMem(g->beg)); 100 CHECK(AddrIsAlignedByGranularity(g->beg)); 101 CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); 102 PoisonShadow(g->beg, g->size_with_redzone, 0); 103 // We unpoison the shadow memory for the global but we do not remove it from 104 // the list because that would require O(n^2) time with the current list 105 // implementation. It might not be worth doing anyway. 106} 107 108} // namespace __asan 109 110// ---------------------- Interface ---------------- {{{1 111using namespace __asan; // NOLINT 112 113// Register one global with a default redzone. 114void __asan_register_global(uptr addr, uptr size, 115 const char *name) { 116 if (!flags()->report_globals) return; 117 ScopedLock lock(&mu_for_globals); 118 Global *g = (Global *)allocator_for_globals.Allocate(sizeof(Global)); 119 g->beg = addr; 120 g->size = size; 121 g->size_with_redzone = GetAlignedSize(size) + kGlobalAndStackRedzone; 122 g->name = name; 123 RegisterGlobal(g); 124} 125 126// Register an array of globals. 127void __asan_register_globals(__asan_global *globals, uptr n) { 128 if (!flags()->report_globals) return; 129 ScopedLock lock(&mu_for_globals); 130 for (uptr i = 0; i < n; i++) { 131 RegisterGlobal(&globals[i]); 132 } 133} 134 135// Unregister an array of globals. 136// We must do it when a shared objects gets dlclosed. 137void __asan_unregister_globals(__asan_global *globals, uptr n) { 138 if (!flags()->report_globals) return; 139 ScopedLock lock(&mu_for_globals); 140 for (uptr i = 0; i < n; i++) { 141 UnregisterGlobal(&globals[i]); 142 } 143} 144