sanitizer_internal_defs.h revision 45418d1ccb083cad3cb84e0b8184adfb85876fc5
144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//===-- sanitizer_internal_defs.h -------------------------------*- C++ -*-===// 243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The LLVM Compiler Infrastructure 443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This file is distributed under the University of Illinois Open Source 643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// License. See LICENSE.TXT for details. 743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//===----------------------------------------------------------------------===// 943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This file is shared between AddressSanitizer and ThreadSanitizer. 1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// It contains macro used in run-time libraries code. 1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//===----------------------------------------------------------------------===// 1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#ifndef SANITIZER_DEFS_H 1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define SANITIZER_DEFS_H 1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "sanitizer/common_interface_defs.h" 1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenusing namespace __sanitizer; // NOLINT 1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------- ATTENTION ------------- 1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This header should NOT include any other headers to avoid portability issues. 2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Common defs. 2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define INLINE static inline 2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE 2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define WEAK SANITIZER_WEAK_ATTRIBUTE 2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Platform-specific defs. 2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#if defined(_WIN32) 2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansentypedef unsigned long DWORD; // NOLINT 2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# define ALWAYS_INLINE __declspec(forceinline) 3043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// FIXME(timurrrr): do we need this on Windows? 31fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org# define ALIAS(x) 3243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# define ALIGNED(x) __declspec(align(x)) 33f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org# define FORMAT(f, a) 34b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define NOINLINE __declspec(noinline) 3565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org# define NORETURN __declspec(noreturn) 36ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org# define THREADLOCAL __declspec(thread) 37dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org# define NOTHROW 3843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#else // _WIN32 39fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org# define ALWAYS_INLINE __attribute__((always_inline)) 4043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# define ALIAS(x) __attribute__((alias(x))) 41b5737496145078e47f3d28f19ed8d918e2254738ager@chromium.org# define ALIGNED(x) __attribute__((aligned(x))) 42a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org# define FORMAT(f, a) __attribute__((format(printf, f, a))) 4343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# define NOINLINE __attribute__((noinline)) 4471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org# define NORETURN __attribute__((noreturn)) 4571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org# define THREADLOCAL __thread 4643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen# ifdef __cplusplus 47b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define NOTHROW throw() 48b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# else 49b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define NOTHROW __attribute__((__nothrow__)) 50b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#endif 51b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#endif // _WIN32 52b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org 53b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org// We have no equivalent of these on Windows. 54b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#ifndef _WIN32 55b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define LIKELY(x) __builtin_expect(!!(x), 1) 56b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define UNLIKELY(x) __builtin_expect(!!(x), 0) 57b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define UNUSED __attribute__((unused)) 58b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define USED __attribute__((used)) 59b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#endif 60b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org 61b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#if defined(_WIN32) 62b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgtypedef DWORD thread_return_t; 63b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define THREAD_CALLING_CONV __stdcall 64b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#else // _WIN32 65b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgtypedef void* thread_return_t; 66b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define THREAD_CALLING_CONV 67b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#endif // _WIN32 68b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgtypedef thread_return_t (THREAD_CALLING_CONV *thread_callback_t)(void* arg); 69b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org 70b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org// If __WORDSIZE was undefined by the platform, define it in terms of the 71b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org// compiler built-ins __LP64__ and _WIN64. 72b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#ifndef __WORDSIZE 73b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# if __LP64__ || defined(_WIN64) 74b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define __WORDSIZE 64 75b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# else 76b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# define __WORDSIZE 32 77b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org# endif 78b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#endif // __WORDSIZE 79b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org 80b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org// NOTE: Functions below must be defined in each run-time. 81b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgnamespace __sanitizer { 82b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgvoid NORETURN Die(); 83b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgvoid NORETURN CheckFailed(const char *file, int line, const char *cond, 84b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org u64 v1, u64 v2); 85b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org} // namespace __sanitizer 86b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org 87a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Check macro 88c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org#define RAW_CHECK_MSG(expr, msg) do { \ 89c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org if (!(expr)) { \ 90c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org RawWrite(msg); \ 91c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org Die(); \ 92c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org } \ 93a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org} while (0) 94c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org 95a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define RAW_CHECK(expr) RAW_CHECK_MSG(expr, #expr) 96a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 97a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK_IMPL(c1, op, c2) \ 98a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org do { \ 99a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org __sanitizer::u64 v1 = (u64)(c1); \ 100a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org __sanitizer::u64 v2 = (u64)(c2); \ 101a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org if (!(v1 op v2)) \ 102c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org __sanitizer::CheckFailed(__FILE__, __LINE__, \ 103a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org "(" #c1 ") " #op " (" #c2 ")", v1, v2); \ 104a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } while (false) \ 105a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/**/ 106a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 107a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK(a) CHECK_IMPL((a), !=, 0) 108a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK_EQ(a, b) CHECK_IMPL((a), ==, (b)) 109a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK_NE(a, b) CHECK_IMPL((a), !=, (b)) 110a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK_LT(a, b) CHECK_IMPL((a), <, (b)) 111a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK_LE(a, b) CHECK_IMPL((a), <=, (b)) 112a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK_GT(a, b) CHECK_IMPL((a), >, (b)) 113a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK_GE(a, b) CHECK_IMPL((a), >=, (b)) 114a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 115a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#if TSAN_DEBUG 116a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK(a) CHECK(a) 117a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_EQ(a, b) CHECK_EQ(a, b) 118c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org#define DCHECK_NE(a, b) CHECK_NE(a, b) 119a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_LT(a, b) CHECK_LT(a, b) 120a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_LE(a, b) CHECK_LE(a, b) 121a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_GT(a, b) CHECK_GT(a, b) 122a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_GE(a, b) CHECK_GE(a, b) 123a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#else 124a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK(a) 125a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_EQ(a, b) 126a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_NE(a, b) 127a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_LT(a, b) 128a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_LE(a, b) 129a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DCHECK_GT(a, b) 13040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org#define DCHECK_GE(a, b) 131a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#endif 132a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 133a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define UNREACHABLE(msg) do { \ 134a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org CHECK(0 && msg); \ 135a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org Die(); \ 136a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org} while(0) 137a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 138a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define UNIMPLEMENTED() UNREACHABLE("unimplemented") 139a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 140a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define COMPILER_CHECK(pred) IMPL_COMPILER_ASSERT(pred, __LINE__) 141a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 142a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 143a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 144a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define IMPL_PASTE(a, b) a##b 145a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define IMPL_COMPILER_ASSERT(pred, line) \ 146a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org typedef char IMPL_PASTE(assertion_failed_##_, line)[2*(int)(pred)-1] 147a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 148a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Limits for integral types. We have to redefine it in case we don't 149a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// have stdint.h (like in Visual Studio 9). 150a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef __INT64_C 151a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef __UINT64_C 152a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#if __WORDSIZE == 64 153a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org# define __INT64_C(c) c ## L 154a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org# define __UINT64_C(c) c ## UL 155a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#else 156a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org# define __INT64_C(c) c ## LL 157a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org# define __UINT64_C(c) c ## ULL 158a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#endif // __WORDSIZE == 64 159a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef INT32_MIN 160a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define INT32_MIN (-2147483647-1) 161a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef INT32_MAX 162a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define INT32_MAX (2147483647) 163a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef UINT32_MAX 164a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define UINT32_MAX (4294967295U) 165a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef INT64_MIN 166a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define INT64_MIN (-__INT64_C(9223372036854775807)-1) 167a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef INT64_MAX 168a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define INT64_MAX (__INT64_C(9223372036854775807)) 169a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef UINT64_MAX 170a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define UINT64_MAX (__UINT64_C(18446744073709551615)) 171a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 172a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgenum LinkerInitialized { LINKER_INITIALIZED = 0 }; 173a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 174a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#if !defined(_MSC_VER) || defined(__clang__) 175a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org# define GET_CALLER_PC() (uptr)__builtin_return_address(0) 176a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org# define GET_CURRENT_FRAME() (uptr)__builtin_frame_address(0) 177a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#else 178a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgextern "C" void* _ReturnAddress(void); 179c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org# pragma intrinsic(_ReturnAddress) 180a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org# define GET_CALLER_PC() (uptr)_ReturnAddress() 181a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// CaptureStackBackTrace doesn't need to know BP on Windows. 182a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// FIXME: This macro is still used when printing error reports though it's not 183a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// clear if the BP value is needed in the ASan reports on Windows. 184a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org# define GET_CURRENT_FRAME() (uptr)0xDEADBEEF 185a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#endif 186a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 187a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define HANDLE_EINTR(res, f) { \ 188a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org do { \ 189a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org res = (f); \ 190a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } while (res == -1 && errno == EINTR); \ 191a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org } 192a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org 193a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#endif // SANITIZER_DEFS_H 194a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org