asan_globals.cc revision b89567ce41bef82cf92a9c741c78b632c07b2781
1//===-- asan_globals.cc -----------------------------------------*- 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// 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_stack.h" 20#include "asan_stats.h" 21#include "asan_thread.h" 22 23#include <ctype.h> 24 25namespace __asan { 26 27typedef __asan_global Global; 28 29struct ListOfGlobals { 30 const Global *g; 31 ListOfGlobals *next; 32}; 33 34static AsanLock mu_for_globals(LINKER_INITIALIZED); 35static ListOfGlobals *list_of_globals; 36static LowLevelAllocator allocator_for_globals(LINKER_INITIALIZED); 37 38void PoisonRedZones(const Global &g) { 39 size_t shadow_rz_size = kGlobalAndStackRedzone >> SHADOW_SCALE; 40 CHECK(shadow_rz_size == 1 || shadow_rz_size == 2 || shadow_rz_size == 4); 41 // full right redzone 42 size_t g_aligned_size = kGlobalAndStackRedzone * 43 ((g.size + kGlobalAndStackRedzone - 1) / kGlobalAndStackRedzone); 44 PoisonShadow(g.beg + g_aligned_size, 45 kGlobalAndStackRedzone, kAsanGlobalRedzoneMagic); 46 if ((g.size % kGlobalAndStackRedzone) != 0) { 47 // partial right redzone 48 uint64_t g_aligned_down_size = kGlobalAndStackRedzone * 49 (g.size / kGlobalAndStackRedzone); 50 CHECK(g_aligned_down_size == g_aligned_size - kGlobalAndStackRedzone); 51 PoisonShadowPartialRightRedzone(g.beg + g_aligned_down_size, 52 g.size % kGlobalAndStackRedzone, 53 kGlobalAndStackRedzone, 54 kAsanGlobalRedzoneMagic); 55 } 56} 57 58static size_t GetAlignedSize(size_t size) { 59 return ((size + kGlobalAndStackRedzone - 1) / kGlobalAndStackRedzone) 60 * kGlobalAndStackRedzone; 61} 62 63 // Check if the global is a zero-terminated ASCII string. If so, print it. 64void PrintIfASCII(const Global &g) { 65 for (size_t p = g.beg; p < g.beg + g.size - 1; p++) { 66 if (!isascii(*(char*)p)) return; 67 } 68 if (*(char*)(g.beg + g.size - 1) != 0) return; 69 Printf(" '%s' is ascii string '%s'\n", g.name, g.beg); 70} 71 72bool DescribeAddrIfMyRedZone(const Global &g, uintptr_t addr) { 73 if (addr < g.beg - kGlobalAndStackRedzone) return false; 74 if (addr >= g.beg + g.size_with_redzone) return false; 75 Printf("%p is located ", addr); 76 if (addr < g.beg) { 77 Printf("%d bytes to the left", g.beg - addr); 78 } else if (addr >= g.beg + g.size) { 79 Printf("%d bytes to the right", addr - (g.beg + g.size)); 80 } else { 81 Printf("%d bytes inside", addr - g.beg); // Can it happen? 82 } 83 Printf(" of global variable '%s' (0x%lx) of size %ld\n", 84 g.name, g.beg, g.size); 85 PrintIfASCII(g); 86 return true; 87} 88 89 90bool DescribeAddrIfGlobal(uintptr_t addr) { 91 if (!FLAG_report_globals) return false; 92 ScopedLock lock(&mu_for_globals); 93 bool res = false; 94 for (ListOfGlobals *l = list_of_globals; l; l = l->next) { 95 const Global &g = *l->g; 96 if (FLAG_report_globals >= 2) 97 Printf("Search Global: beg=%p size=%ld name=%s\n", 98 g.beg, g.size, g.name); 99 res |= DescribeAddrIfMyRedZone(g, addr); 100 } 101 return res; 102} 103 104// Register a global variable. 105// This function may be called more than once for every global 106// so we store the globals in a map. 107static void RegisterGlobal(const Global *g) { 108 CHECK(asan_inited); 109 if (!FLAG_report_globals) return; 110 ScopedLock lock(&mu_for_globals); 111 CHECK(AddrIsInMem(g->beg)); 112 CHECK(AddrIsAlignedByGranularity(g->beg)); 113 PoisonRedZones(*g); 114 ListOfGlobals *l = 115 (ListOfGlobals*)allocator_for_globals.Allocate(sizeof(ListOfGlobals)); 116 l->g = g; 117 l->next = list_of_globals; 118 list_of_globals = l; 119 if (FLAG_report_globals >= 2) 120 Printf("Added Global: beg=%p size=%ld name=%s\n", 121 g->beg, g->size, g->name); 122} 123 124} // namespace __asan 125 126// ---------------------- Interface ---------------- {{{1 127using namespace __asan; // NOLINT 128 129// Register one global with a default redzone. 130void __asan_register_global(uintptr_t addr, size_t size, 131 const char *name) { 132 Global g; 133 g.beg = addr; 134 g.size = size; 135 g.size_with_redzone = GetAlignedSize(size) + kGlobalAndStackRedzone; 136 g.name = name; 137 RegisterGlobal(&g); 138} 139 140// Register an array of globals. 141void __asan_register_globals(__asan_global *globals, size_t n) { 142 for (size_t i = 0; i < n; i++) { 143 RegisterGlobal(&globals[i]); 144 } 145} 146