asan_globals.cc revision 1e172b4bdec57329bf904f063a29f99cddf2d85f
1f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com//===-- asan_globals.cc -----------------------------------------*- C++ -*-===// 2f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// 3f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// The LLVM Compiler Infrastructure 4f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// 5f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// This file is distributed under the University of Illinois Open Source 6f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// License. See LICENSE.TXT for details. 7f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// 8f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com//===----------------------------------------------------------------------===// 9f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// 10f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// This file is a part of AddressSanitizer, an address sanity checker. 11f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// 123f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org// Handle globals. 13f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com//===----------------------------------------------------------------------===// 14f47223d0c72e105acf8247446ba94255467dff77kjellander@webrtc.org#include "asan_interceptors.h" 15f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com#include "asan_interface.h" 16cff5c03bbf63004ab85478a5660d341d3366ef63pbos@webrtc.org#include "asan_internal.h" 17f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com#include "asan_lock.h" 18f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com#include "asan_mapping.h" 19f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com#include "asan_stack.h" 20f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com#include "asan_stats.h" 21f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com#include "asan_thread.h" 22f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 23f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com#include <ctype.h> 24f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com#include <map> 25f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 26f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.comnamespace __asan { 27f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 28f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.comtypedef __asan_global Global; 29f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 30f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.comstatic AsanLock mu_for_globals(LINKER_INITIALIZED); 31f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.comtypedef std::map<uintptr_t, Global> MapOfGlobals; 329f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.orgstatic MapOfGlobals *g_all_globals = NULL; 339f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org 349f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.orgvoid PoisonRedZones(const Global &g) { 359f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org uintptr_t shadow = MemToShadow(g.beg); 36f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com size_t ShadowRZSize = kGlobalAndStackRedzone >> SHADOW_SCALE; 37f47223d0c72e105acf8247446ba94255467dff77kjellander@webrtc.org CHECK(ShadowRZSize == 1 || ShadowRZSize == 2 || ShadowRZSize == 4); 38f47223d0c72e105acf8247446ba94255467dff77kjellander@webrtc.org // full right redzone 399f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org uintptr_t right_rz2_offset = ShadowRZSize * 40f47223d0c72e105acf8247446ba94255467dff77kjellander@webrtc.org ((g.size + kGlobalAndStackRedzone - 1) / kGlobalAndStackRedzone); 41f47223d0c72e105acf8247446ba94255467dff77kjellander@webrtc.org real_memset((uint8_t*)shadow + right_rz2_offset, 42f47223d0c72e105acf8247446ba94255467dff77kjellander@webrtc.org kAsanGlobalRedzoneMagic, ShadowRZSize); 439f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org if ((g.size % kGlobalAndStackRedzone) != 0) { 44f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com // partial right redzone 45f47223d0c72e105acf8247446ba94255467dff77kjellander@webrtc.org uint64_t right_rz1_offset = 46f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com ShadowRZSize * (g.size / kGlobalAndStackRedzone); 47f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com CHECK(right_rz1_offset == right_rz2_offset - ShadowRZSize); 48f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com PoisonShadowPartialRightRedzone((uint8_t*)(shadow + right_rz1_offset), 49f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com g.size % kGlobalAndStackRedzone, 50f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com kGlobalAndStackRedzone, 51f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com SHADOW_GRANULARITY, 52f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com kAsanGlobalRedzoneMagic); 53f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com } 54f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com} 55f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 56ba47616ee5a8d8a4d94e160b64b79a56845e291bandrew@webrtc.orgstatic size_t GetAlignedSize(size_t size) { 57ba47616ee5a8d8a4d94e160b64b79a56845e291bandrew@webrtc.org return ((size + kGlobalAndStackRedzone - 1) / kGlobalAndStackRedzone) 58f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com * kGlobalAndStackRedzone; 59f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com} 60f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 61f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com // Check if the global is a zero-terminated ASCII string. If so, print it. 62f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.comvoid PrintIfASCII(const Global &g) { 63f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com for (size_t p = g.beg; p < g.beg + g.size - 1; p++) { 64f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (!isascii(*(char*)p)) return; 65f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com } 66f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (*(char*)(g.beg + g.size - 1) != 0) return; 67f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com Printf(" '%s' is ascii string '%s'\n", g.name, g.beg); 68f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com} 69f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 70f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.combool DescribeAddrIfMyRedZone(const Global &g, uintptr_t addr) { 71f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (addr < g.beg - kGlobalAndStackRedzone) return false; 72f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (addr >= g.beg + g.size_with_redzone) return false; 73f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com Printf("%p is located ", addr); 74f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (addr < g.beg) { 75f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com Printf("%d bytes to the left", g.beg - addr); 769f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org } else if (addr >= g.beg + g.size) { 779f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org Printf("%d bytes to the right", addr - (g.beg + g.size)); 78f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com } else { 79f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com Printf("%d bytes inside", addr - g.beg); // Can it happen? 80f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com } 81ba47616ee5a8d8a4d94e160b64b79a56845e291bandrew@webrtc.org Printf(" of global variable '%s' (0x%lx) of size %ld\n", 82ba47616ee5a8d8a4d94e160b64b79a56845e291bandrew@webrtc.org g.name, g.beg, g.size); 83f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com PrintIfASCII(g); 84f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com return true; 85f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com} 86f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 87f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 88f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.combool DescribeAddrIfGlobal(uintptr_t addr) { 89f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (!FLAG_report_globals) return false; 90f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com ScopedLock lock(&mu_for_globals); 919f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org if (!g_all_globals) return false; 929f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org bool res = false; 939f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org // Just iterate. May want to use binary search instead. 94f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com for (MapOfGlobals::iterator i = g_all_globals->begin(), 95f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com end = g_all_globals->end(); i != end; ++i) { 96f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com Global &g = i->second; 97f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com CHECK(i->first == g.beg); 98f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (FLAG_report_globals >= 2) 99f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com Printf("Search Global: beg=%p size=%ld name=%s\n", 100f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com g.beg, g.size, g.name); 101f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com res |= DescribeAddrIfMyRedZone(g, addr); 102f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com } 103f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com return res; 104f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com} 105f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 106f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// Register a global variable. 107f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// This function may be called more than once for every global 108f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// so we store the globals in a map. 109f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.comstatic void RegisterGlobal(const Global *g) { 110f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com CHECK(asan_inited); 111f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (!FLAG_report_globals) return; 112f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com ScopedLock lock(&mu_for_globals); 113f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (!g_all_globals) 114f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com g_all_globals = new MapOfGlobals; 115f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com CHECK(AddrIsInMem(g->beg)); 116f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com if (FLAG_report_globals >= 2) 117f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com Printf("Added Global: beg=%p size=%ld name=%s\n", 118f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com g->beg, g->size, g->name); 119f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com PoisonRedZones(*g); 120f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com (*g_all_globals)[g->beg] = *g; 121f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com} 1229f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org 1239f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org} // namespace __asan 1249f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org 125f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// ---------------------- Interface ---------------- {{{1 126f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.comusing namespace __asan; // NOLINT 127f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 128f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// Register one global with a default redzone. 1299f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.orgvoid __asan_register_global(uintptr_t addr, size_t size, 130f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com const char *name) { 131f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com Global g; 132f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com g.beg = addr; 133f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com g.size = size; 134f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com g.size_with_redzone = GetAlignedSize(size) + kGlobalAndStackRedzone; 1359f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org g.name = name; 1369f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org RegisterGlobal(&g); 137f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com} 138f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com 139f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com// Register an array of globals. 140f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.comvoid __asan_register_globals(__asan_global *globals, size_t n) { 141f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com for (size_t i = 0; i < n; i++) { 142f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com RegisterGlobal(&globals[i]); 143f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com } 144f8b1da2faffe818a2d85e8904d2c4f09e5db4d5cbrykt@google.com} 1459f4ae03d99cc213b797f49afb737a7a4fe98454ckjellander@webrtc.org