merge(3p/glog): Vendor glog from commit 'afe04691'

This commit is contained in:
Vincent Ambo 2020-05-27 01:26:30 +01:00
commit 6941048b7e
133 changed files with 23455 additions and 0 deletions

View file

@ -0,0 +1,133 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// This file is a compatibility layer that defines Google's version of
// command line flags that are used for configuration.
//
// We put flags into their own namespace. It is purposefully
// named in an opaque way that people should have trouble typing
// directly. The idea is that DEFINE puts the flag in the weird
// namespace, and DECLARE imports the flag from there into the
// current namespace. The net result is to force people to use
// DECLARE to get access to a flag, rather than saying
// extern bool FLAGS_logtostderr;
// or some such instead. We want this so we can put extra
// functionality (like sanity-checking) in DECLARE if we want,
// and make sure it is picked up everywhere.
//
// We also put the type of the variable in the namespace, so that
// people can't DECLARE_int32 something that they DEFINE_bool'd
// elsewhere.
#ifndef BASE_COMMANDLINEFLAGS_H__
#define BASE_COMMANDLINEFLAGS_H__
#include "config.h"
#include <string>
#include <string.h> // for memchr
#include <stdlib.h> // for getenv
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
#else
#include "glog/logging.h"
#define DECLARE_VARIABLE(type, shorttype, name, tn) \
namespace fL##shorttype { \
extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \
} \
using fL##shorttype::FLAGS_##name
#define DEFINE_VARIABLE(type, shorttype, name, value, meaning, tn) \
namespace fL##shorttype { \
GOOGLE_GLOG_DLL_DECL type FLAGS_##name(value); \
char FLAGS_no##name; \
} \
using fL##shorttype::FLAGS_##name
// bool specialization
#define DECLARE_bool(name) \
DECLARE_VARIABLE(bool, B, name, bool)
#define DEFINE_bool(name, value, meaning) \
DEFINE_VARIABLE(bool, B, name, value, meaning, bool)
// int32 specialization
#define DECLARE_int32(name) \
DECLARE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, int32)
#define DEFINE_int32(name, value, meaning) \
DEFINE_VARIABLE(GOOGLE_NAMESPACE::int32, I, name, value, meaning, int32)
// Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery.
#define DECLARE_string(name) \
namespace fLS { \
extern GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#define DEFINE_string(name, value, meaning) \
namespace fLS { \
std::string FLAGS_##name##_buf(value); \
GOOGLE_GLOG_DLL_DECL std::string& FLAGS_##name = FLAGS_##name##_buf; \
char FLAGS_no##name; \
} \
using fLS::FLAGS_##name
#endif // HAVE_LIB_GFLAGS
// Define GLOG_DEFINE_* using DEFINE_* . By using these macros, we
// have GLOG_* environ variables even if we have gflags installed.
//
// If both an environment variable and a flag are specified, the value
// specified by a flag wins. E.g., if GLOG_v=0 and --v=1, the
// verbosity will be 1, not 0.
#define GLOG_DEFINE_bool(name, value, meaning) \
DEFINE_bool(name, EnvToBool("GLOG_" #name, value), meaning)
#define GLOG_DEFINE_int32(name, value, meaning) \
DEFINE_int32(name, EnvToInt("GLOG_" #name, value), meaning)
#define GLOG_DEFINE_string(name, value, meaning) \
DEFINE_string(name, EnvToString("GLOG_" #name, value), meaning)
// These macros (could be functions, but I don't want to bother with a .cc
// file), make it easier to initialize flags from the environment.
#define EnvToString(envname, dflt) \
(!getenv(envname) ? (dflt) : getenv(envname))
#define EnvToBool(envname, dflt) \
(!getenv(envname) ? (dflt) : memchr("tTyY1\0", getenv(envname)[0], 6) != NULL)
#define EnvToInt(envname, dflt) \
(!getenv(envname) ? (dflt) : strtol(getenv(envname), NULL, 10))
#endif // BASE_COMMANDLINEFLAGS_H__

51
third_party/glog/src/base/googleinit.h vendored Normal file
View file

@ -0,0 +1,51 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Jacob Hoffman-Andrews
#ifndef _GOOGLEINIT_H
#define _GOOGLEINIT_H
class GoogleInitializer {
public:
typedef void (*void_function)(void);
GoogleInitializer(const char*, void_function f) {
f();
}
};
#define REGISTER_MODULE_INITIALIZER(name, body) \
namespace { \
static void google_init_module_##name () { body; } \
GoogleInitializer google_initializer_module_##name(#name, \
google_init_module_##name); \
}
#endif /* _GOOGLEINIT_H */

333
third_party/glog/src/base/mutex.h vendored Normal file
View file

@ -0,0 +1,333 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
// Author: Craig Silverstein.
//
// A simple mutex wrapper, supporting locks and read-write locks.
// You should assume the locks are *not* re-entrant.
//
// To use: you should define the following macros in your configure.ac:
// ACX_PTHREAD
// AC_RWLOCK
// The latter is defined in ../autoconf.
//
// This class is meant to be internal-only and should be wrapped by an
// internal namespace. Before you use this module, please give the
// name of your internal namespace for this module. Or, if you want
// to expose it, you'll want to move it to the Google namespace. We
// cannot put this class in global namespace because there can be some
// problems when we have multiple versions of Mutex in each shared object.
//
// NOTE: by default, we have #ifdef'ed out the TryLock() method.
// This is for two reasons:
// 1) TryLock() under Windows is a bit annoying (it requires a
// #define to be defined very early).
// 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG
// mode.
// If you need TryLock(), and either these two caveats are not a
// problem for you, or you're willing to work around them, then
// feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs
// in the code below.
//
// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy:
// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html
// Because of that, we might as well use windows locks for
// cygwin. They seem to be more reliable than the cygwin pthreads layer.
//
// TRICKY IMPLEMENTATION NOTE:
// This class is designed to be safe to use during
// dynamic-initialization -- that is, by global constructors that are
// run before main() starts. The issue in this case is that
// dynamic-initialization happens in an unpredictable order, and it
// could be that someone else's dynamic initializer could call a
// function that tries to acquire this mutex -- but that all happens
// before this mutex's constructor has run. (This can happen even if
// the mutex and the function that uses the mutex are in the same .cc
// file.) Basically, because Mutex does non-trivial work in its
// constructor, it's not, in the naive implementation, safe to use
// before dynamic initialization has run on it.
//
// The solution used here is to pair the actual mutex primitive with a
// bool that is set to true when the mutex is dynamically initialized.
// (Before that it's false.) Then we modify all mutex routines to
// look at the bool, and not try to lock/unlock until the bool makes
// it to true (which happens after the Mutex constructor has run.)
//
// This works because before main() starts -- particularly, during
// dynamic initialization -- there are no threads, so a) it's ok that
// the mutex operations are a no-op, since we don't need locking then
// anyway; and b) we can be quite confident our bool won't change
// state between a call to Lock() and a call to Unlock() (that would
// require a global constructor in one translation unit to call Lock()
// and another global constructor in another translation unit to call
// Unlock() later, which is pretty perverse).
//
// That said, it's tricky, and can conceivably fail; it's safest to
// avoid trying to acquire a mutex in a global constructor, if you
// can. One way it can fail is that a really smart compiler might
// initialize the bool to true at static-initialization time (too
// early) rather than at dynamic-initialization time. To discourage
// that, we set is_safe_ to true in code (not the constructor
// colon-initializer) and set it to true via a function that always
// evaluates to true, but that the compiler can't know always
// evaluates to true. This should be good enough.
#ifndef GOOGLE_MUTEX_H_
#define GOOGLE_MUTEX_H_
#include "config.h" // to figure out pthreads support
#if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif
# ifdef GMUTEX_TRYLOCK
// We need Windows NT or later for TryEnterCriticalSection(). If you
// don't need that functionality, you can remove these _WIN32_WINNT
// lines, and change TryLock() to assert(0) or something.
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0400
# endif
# endif
// To avoid macro definition of ERROR.
# ifndef NOGDI
# define NOGDI
# endif
// To avoid macro definition of min/max.
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
typedef CRITICAL_SECTION MutexType;
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
// Needed for pthread_rwlock_*. If it causes problems, you could take it
// out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed
// for locking there.)
# ifdef __linux__
# ifndef _XOPEN_SOURCE // Some other header might have already set it for us.
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
# endif
# endif
# include <pthread.h>
typedef pthread_rwlock_t MutexType;
#elif defined(HAVE_PTHREAD)
# include <pthread.h>
typedef pthread_mutex_t MutexType;
#else
# error Need to implement mutex.h for your architecture, or #define NO_THREADS
#endif
// We need to include these header files after defining _XOPEN_SOURCE
// as they may define the _XOPEN_SOURCE macro.
#include <assert.h>
#include <stdlib.h> // for abort()
#define MUTEX_NAMESPACE glog_internal_namespace_
namespace MUTEX_NAMESPACE {
class Mutex {
public:
// Create a Mutex that is not held by anybody. This constructor is
// typically used for Mutexes allocated on the heap or the stack.
// See below for a recommendation for constructing global Mutex
// objects.
inline Mutex();
// Destructor
inline ~Mutex();
inline void Lock(); // Block if needed until free then acquire exclusively
inline void Unlock(); // Release a lock acquired via Lock()
#ifdef GMUTEX_TRYLOCK
inline bool TryLock(); // If free, Lock() and return true, else return false
#endif
// Note that on systems that don't support read-write locks, these may
// be implemented as synonyms to Lock() and Unlock(). So you can use
// these for efficiency, but don't use them anyplace where being able
// to do shared reads is necessary to avoid deadlock.
inline void ReaderLock(); // Block until free or shared then acquire a share
inline void ReaderUnlock(); // Release a read share of this Mutex
inline void WriterLock() { Lock(); } // Acquire an exclusive lock
inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
// TODO(hamaji): Do nothing, implement correctly.
inline void AssertHeld() {}
private:
MutexType mutex_;
// We want to make sure that the compiler sets is_safe_ to true only
// when we tell it to, and never makes assumptions is_safe_ is
// always true. volatile is the most reliable way to do that.
volatile bool is_safe_;
inline void SetIsSafe() { is_safe_ = true; }
// Catch the error of writing Mutex when intending MutexLock.
Mutex(Mutex* /*ignored*/) {}
// Disallow "evil" constructors
Mutex(const Mutex&);
void operator=(const Mutex&);
};
// Now the implementation of Mutex for various systems
#if defined(NO_THREADS)
// When we don't have threads, we can be either reading or writing,
// but not both. We can have lots of readers at once (in no-threads
// mode, that's most likely to happen in recursive function calls),
// but only one writer. We represent this by having mutex_ be -1 when
// writing and a number > 0 when reading (and 0 when no lock is held).
//
// In debug mode, we assert these invariants, while in non-debug mode
// we do nothing, for efficiency. That's why everything is in an
// assert.
Mutex::Mutex() : mutex_(0) { }
Mutex::~Mutex() { assert(mutex_ == 0); }
void Mutex::Lock() { assert(--mutex_ == -1); }
void Mutex::Unlock() { assert(mutex_++ == -1); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; }
#endif
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); }
Mutex::~Mutex() { DeleteCriticalSection(&mutex_); }
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
TryEnterCriticalSection(&mutex_) != 0 : true; }
#endif
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
void Mutex::ReaderUnlock() { Unlock(); }
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() {
SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
}
Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_rwlock_trywrlock(&mutex_) == 0 :
true; }
#endif
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#undef SAFE_PTHREAD
#elif defined(HAVE_PTHREAD)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() {
SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
}
Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
#ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ?
pthread_mutex_trylock(&mutex_) == 0 : true; }
#endif
void Mutex::ReaderLock() { Lock(); }
void Mutex::ReaderUnlock() { Unlock(); }
#undef SAFE_PTHREAD
#endif
// --------------------------------------------------------------------------
// Some helper classes
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
class MutexLock {
public:
explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
~MutexLock() { mu_->Unlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
MutexLock(const MutexLock&);
void operator=(const MutexLock&);
};
// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
class ReaderMutexLock {
public:
explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
~ReaderMutexLock() { mu_->ReaderUnlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
ReaderMutexLock(const ReaderMutexLock&);
void operator=(const ReaderMutexLock&);
};
class WriterMutexLock {
public:
explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
~WriterMutexLock() { mu_->WriterUnlock(); }
private:
Mutex * const mu_;
// Disallow "evil" constructors
WriterMutexLock(const WriterMutexLock&);
void operator=(const WriterMutexLock&);
};
// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
} // namespace MUTEX_NAMESPACE
using namespace MUTEX_NAMESPACE;
#undef MUTEX_NAMESPACE
#endif /* #define GOOGLE_MUTEX_H__ */

219
third_party/glog/src/config.h.cmake.in vendored Normal file
View file

@ -0,0 +1,219 @@
#ifndef GLOG_CONFIG_H
#define GLOG_CONFIG_H
/* define if glog doesn't use RTTI */
#cmakedefine DISABLE_RTTI
/* Namespace for Google classes */
#cmakedefine GOOGLE_NAMESPACE ${GOOGLE_NAMESPACE}
/* Define if you have the `dladdr' function */
#cmakedefine HAVE_DLADDR
/* Define if you have the `snprintf' function */
#cmakedefine HAVE_SNPRINTF
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H
/* Define to 1 if you have the <execinfo.h> header file. */
#cmakedefine HAVE_EXECINFO_H
/* Define if you have the `fcntl' function */
#cmakedefine HAVE_FCNTL
/* Define to 1 if you have the <glob.h> header file. */
#cmakedefine HAVE_GLOB_H
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H}
/* Define to 1 if you have the `pthread' library (-lpthread). */
#cmakedefine HAVE_LIBPTHREAD
/* Define to 1 if you have the <libunwind.h> header file. */
#cmakedefine HAVE_LIBUNWIND_H
/* define if you have google gflags library */
#cmakedefine HAVE_LIB_GFLAGS
/* define if you have google gmock library */
#cmakedefine HAVE_LIB_GMOCK
/* define if you have google gtest library */
#cmakedefine HAVE_LIB_GTEST
/* define if you have libunwind */
#cmakedefine HAVE_LIB_UNWIND
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H
/* define to disable multithreading support. */
#cmakedefine NO_THREADS
/* define if the compiler implements namespaces */
#cmakedefine HAVE_NAMESPACES
/* Define if you have the 'pread' function */
#cmakedefine HAVE_PREAD
/* Define if you have POSIX threads libraries and header files. */
#cmakedefine HAVE_PTHREAD
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H
/* Define if you have the 'pwrite' function */
#cmakedefine HAVE_PWRITE
/* define if the compiler implements pthread_rwlock_* */
#cmakedefine HAVE_RWLOCK
/* Define if you have the 'sigaction' function */
#cmakedefine HAVE_SIGACTION
/* Define if you have the `sigaltstack' function */
#cmakedefine HAVE_SIGALTSTACK
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H}
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H
/* Define to 1 if you have the <syscall.h> header file. */
#cmakedefine HAVE_SYSCALL_H
/* Define to 1 if you have the <syslog.h> header file. */
#cmakedefine HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/syscall.h> header file. */
#cmakedefine HAVE_SYS_SYSCALL_H
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H}
/* Define to 1 if you have the <sys/ucontext.h> header file. */
#cmakedefine HAVE_SYS_UCONTEXT_H
/* Define to 1 if you have the <sys/utsname.h> header file. */
#cmakedefine HAVE_SYS_UTSNAME_H
/* Define to 1 if you have the <sys/wait.h> header file. */
#cmakedefine HAVE_SYS_WAIT_H
/* Define to 1 if you have the <ucontext.h> header file. */
#cmakedefine HAVE_UCONTEXT_H
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
/* Define to 1 if you have the <unwind.h> header file. */
#cmakedefine HAVE_UNWIND_H ${HAVE_UNWIND_H}
/* define if the compiler supports using expression for operator */
#cmakedefine HAVE_USING_OPERATOR
/* define if your compiler has __attribute__ */
#cmakedefine HAVE___ATTRIBUTE__
/* define if your compiler has __builtin_expect */
#cmakedefine HAVE___BUILTIN_EXPECT ${HAVE___BUILTIN_EXPECT}
/* define if your compiler has __sync_val_compare_and_swap */
#cmakedefine HAVE___SYNC_VAL_COMPARE_AND_SWAP
/* define if symbolize support is available */
#cmakedefine HAVE_SYMBOLIZE
/* define if localtime_r is available in time.h */
#cmakedefine HAVE_LOCALTIME_R
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#cmakedefine LT_OBJDIR
/* Name of package */
#cmakedefine PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#cmakedefine PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#cmakedefine PACKAGE_NAME
/* Define to the full name and version of this package. */
#cmakedefine PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#cmakedefine PACKAGE_TARNAME
/* Define to the home page for this package. */
#cmakedefine PACKAGE_URL
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION
/* How to access the PC from a struct ucontext */
#cmakedefine PC_FROM_UCONTEXT
/* define if we should print file offsets in traces instead of symbolizing. */
#cmakedefine PRINT_UNSYMBOLIZED_STACK_TRACES
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#cmakedefine PTHREAD_CREATE_JOINABLE
/* The size of `void *', as computed by sizeof. */
#cmakedefine SIZEOF_VOID_P ${SIZEOF_VOID_P}
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS
/* the namespace where STL code like vector<> is defined */
#cmakedefine STL_NAMESPACE ${STL_NAMESPACE}
/* location of source code */
#cmakedefine TEST_SRC_DIR ${TEST_SRC_DIR}
/* Define to necessary thread-local storage attribute. */
#cmakedefine GLOG_THREAD_LOCAL_STORAGE ${GLOG_THREAD_LOCAL_STORAGE}
/* Check whether aligned_storage and alignof present */
#cmakedefine HAVE_ALIGNED_STORAGE ${HAVE_ALIGNED_STORAGE}
/* Version number of package */
#cmakedefine VERSION
#ifdef GLOG_BAZEL_BUILD
/* TODO(rodrigoq): remove this workaround once bazel#3979 is resolved:
* https://github.com/bazelbuild/bazel/issues/3979 */
#define _START_GOOGLE_NAMESPACE_ namespace GOOGLE_NAMESPACE {
#define _END_GOOGLE_NAMESPACE_ }
#else
/* Stops putting the code inside the Google namespace */
#cmakedefine _END_GOOGLE_NAMESPACE_ ${_END_GOOGLE_NAMESPACE_}
/* Puts following code inside the Google namespace */
#cmakedefine _START_GOOGLE_NAMESPACE_ ${_START_GOOGLE_NAMESPACE_}
#endif
#endif // GLOG_CONFIG_H

View file

@ -0,0 +1,66 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// All Rights Reserved.
//
// Author: Craig Silverstein
// Copied from google-perftools and modified by Shinichiro Hamaji
//
// This file is needed for windows -- unittests are not part of the
// glog dll, but still want to include config.h just like the
// dll does, so they can use internal tools and APIs for testing.
//
// The problem is that config.h declares GOOGLE_GLOG_DLL_DECL to be
// for exporting symbols, but the unittest needs to *import* symbols
// (since it's not the dll).
//
// The solution is to have this file, which is just like config.h but
// sets GOOGLE_GLOG_DLL_DECL to do a dllimport instead of a dllexport.
//
// The reason we need this extra GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
// variable is in case people want to set GOOGLE_GLOG_DLL_DECL explicitly
// to something other than __declspec(dllexport). In that case, they
// may want to use something other than __declspec(dllimport) for the
// unittest case. For that, we allow folks to define both
// GOOGLE_GLOG_DLL_DECL and GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS explicitly.
//
// NOTE: This file is equivalent to config.h on non-windows systems,
// which never defined GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS and always
// define GOOGLE_GLOG_DLL_DECL to the empty string.
#include "config.h"
#undef GOOGLE_GLOG_DLL_DECL
#ifdef GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
# define GOOGLE_GLOG_DLL_DECL GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS
#else
// if DLL_DECL_FOR_UNITTESTS isn't defined, use ""
# define GOOGLE_GLOG_DLL_DECL
#endif

1356
third_party/glog/src/demangle.cc vendored Normal file

File diff suppressed because it is too large Load diff

85
third_party/glog/src/demangle.h vendored Normal file
View file

@ -0,0 +1,85 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// An async-signal-safe and thread-safe demangler for Itanium C++ ABI
// (aka G++ V3 ABI).
// The demangler is implemented to be used in async signal handlers to
// symbolize stack traces. We cannot use libstdc++'s
// abi::__cxa_demangle() in such signal handlers since it's not async
// signal safe (it uses malloc() internally).
//
// Note that this demangler doesn't support full demangling. More
// specifically, it doesn't print types of function parameters and
// types of template arguments. It just skips them. However, it's
// still very useful to extract basic information such as class,
// function, constructor, destructor, and operator names.
//
// See the implementation note in demangle.cc if you are interested.
//
// Example:
//
// | Mangled Name | The Demangler | abi::__cxa_demangle()
// |---------------|---------------|-----------------------
// | _Z1fv | f() | f()
// | _Z1fi | f() | f(int)
// | _Z3foo3bar | foo() | foo(bar)
// | _Z1fIiEvi | f<>() | void f<int>(int)
// | _ZN1N1fE | N::f | N::f
// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar()
// | _Zrm1XS_" | operator%() | operator%(X, X)
// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo()
// | _Z1fSs | f() | f(std::basic_string<char,
// | | | std::char_traits<char>,
// | | | std::allocator<char> >)
//
// See the unit test for more examples.
//
// Note: we might want to write demanglers for ABIs other than Itanium
// C++ ABI in the future.
//
#ifndef BASE_DEMANGLE_H_
#define BASE_DEMANGLE_H_
#include "config.h"
#include "glog/logging.h"
_START_GOOGLE_NAMESPACE_
// Demangle "mangled". On success, return true and write the
// demangled symbol name to "out". Otherwise, return false.
// "out" is modified even if demangling is unsuccessful.
bool GOOGLE_GLOG_DLL_DECL Demangle(const char *mangled, char *out, int out_size);
_END_GOOGLE_NAMESPACE_
#endif // BASE_DEMANGLE_H_

View file

@ -0,0 +1,168 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// Unit tests for functions in demangle.c.
#include "utilities.h"
#include <iostream>
#include <fstream>
#include <string>
#include "glog/logging.h"
#include "demangle.h"
#include "googletest.h"
#include "config.h"
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE;
#endif
GLOG_DEFINE_bool(demangle_filter, false,
"Run demangle_unittest in filter mode");
using namespace std;
using namespace GOOGLE_NAMESPACE;
// A wrapper function for Demangle() to make the unit test simple.
static const char *DemangleIt(const char * const mangled) {
static char demangled[4096];
if (Demangle(mangled, demangled, sizeof(demangled))) {
return demangled;
} else {
return mangled;
}
}
#if defined(OS_WINDOWS)
TEST(Demangle, Windows) {
EXPECT_STREQ(
"public: static void __cdecl Foo::func(int)",
DemangleIt("?func@Foo@@SAXH@Z"));
EXPECT_STREQ(
"public: static void __cdecl Foo::func(int)",
DemangleIt("@ILT+1105(?func@Foo@@SAXH@Z)"));
EXPECT_STREQ(
"int __cdecl foobarArray(int * const)",
DemangleIt("?foobarArray@@YAHQAH@Z"));
}
#else
// Test corner cases of bounary conditions.
TEST(Demangle, CornerCases) {
const size_t size = 10;
char tmp[size] = { 0 };
const char *demangled = "foobar()";
const char *mangled = "_Z6foobarv";
EXPECT_TRUE(Demangle(mangled, tmp, sizeof(tmp)));
// sizeof("foobar()") == size - 1
EXPECT_STREQ(demangled, tmp);
EXPECT_TRUE(Demangle(mangled, tmp, size - 1));
EXPECT_STREQ(demangled, tmp);
EXPECT_FALSE(Demangle(mangled, tmp, size - 2)); // Not enough.
EXPECT_FALSE(Demangle(mangled, tmp, 1));
EXPECT_FALSE(Demangle(mangled, tmp, 0));
EXPECT_FALSE(Demangle(mangled, NULL, 0)); // Should not cause SEGV.
}
// Test handling of functions suffixed with .clone.N, which is used by GCC
// 4.5.x, and .constprop.N and .isra.N, which are used by GCC 4.6.x. These
// suffixes are used to indicate functions which have been cloned during
// optimization. We ignore these suffixes.
TEST(Demangle, Clones) {
char tmp[20];
EXPECT_TRUE(Demangle("_ZL3Foov", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.clone.3", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.constprop.80", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.isra.18", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
// Invalid (truncated), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
// Invalid (.clone. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
// Invalid (.clone. followed by non-number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
// Invalid (.constprop. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
}
TEST(Demangle, FromFile) {
string test_file = FLAGS_test_srcdir + "/src/demangle_unittest.txt";
ifstream f(test_file.c_str()); // The file should exist.
EXPECT_FALSE(f.fail());
string line;
while (getline(f, line)) {
// Lines start with '#' are considered as comments.
if (line.empty() || line[0] == '#') {
continue;
}
// Each line should contain a mangled name and a demangled name
// separated by '\t'. Example: "_Z3foo\tfoo"
string::size_type tab_pos = line.find('\t');
EXPECT_NE(string::npos, tab_pos);
string mangled = line.substr(0, tab_pos);
string demangled = line.substr(tab_pos + 1);
EXPECT_EQ(demangled, DemangleIt(mangled.c_str()));
}
}
#endif
int main(int argc, char **argv) {
#ifdef HAVE_LIB_GFLAGS
ParseCommandLineFlags(&argc, &argv, true);
#endif
InitGoogleTest(&argc, argv);
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
if (FLAGS_demangle_filter) {
// Read from cin and write to cout.
string line;
while (getline(cin, line, '\n')) {
cout << DemangleIt(line.c_str()) << endl;
}
return 0;
} else if (argc > 1) {
cout << DemangleIt(argv[1]) << endl;
return 0;
} else {
return RUN_ALL_TESTS();
}
}

95
third_party/glog/src/demangle_unittest.sh vendored Executable file
View file

@ -0,0 +1,95 @@
#! /bin/sh
#
# Copyright (c) 2006, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Satoru Takabayashi
#
# Unit tests for demangle.c with a real binary.
set -e
die () {
echo $1
exit 1
}
BINDIR=".libs"
LIBGLOG="$BINDIR/libglog.so"
DEMANGLER="$BINDIR/demangle_unittest"
if test -e "$DEMANGLER"; then
# We need shared object.
export LD_LIBRARY_PATH=$BINDIR
export DYLD_LIBRARY_PATH=$BINDIR
else
# For windows
DEMANGLER="./demangle_unittest.exe"
if ! test -e "$DEMANGLER"; then
echo "We coundn't find demangle_unittest binary."
exit 1
fi
fi
# Extract C++ mangled symbols from libbase.so.
NM_OUTPUT="demangle.nm"
nm "$LIBGLOG" | perl -nle 'print $1 if /\s(_Z\S+$)/' > "$NM_OUTPUT"
# Check if mangled symbols exist. If there are none, we quit.
# The binary is more likely compiled with GCC 2.95 or something old.
if ! grep --quiet '^_Z' "$NM_OUTPUT"; then
echo "PASS"
exit 0
fi
# Demangle the symbols using our demangler.
DM_OUTPUT="demangle.dm"
GLOG_demangle_filter=1 "$DEMANGLER" --demangle_filter < "$NM_OUTPUT" > "$DM_OUTPUT"
# Calculate the numbers of lines.
NM_LINES=`wc -l "$NM_OUTPUT" | awk '{ print $1 }'`
DM_LINES=`wc -l "$DM_OUTPUT" | awk '{ print $1 }'`
# Compare the numbers of lines. They must be the same.
if test "$NM_LINES" != "$DM_LINES"; then
die "$NM_OUTPUT and $DM_OUTPUT don't have the same numbers of lines"
fi
# Check if mangled symbols exist. They must not exist.
if grep --quiet '^_Z' "$DM_OUTPUT"; then
MANGLED=`grep '^_Z' "$DM_OUTPUT" | wc -l | awk '{ print \$1 }'`
echo "Mangled symbols ($MANGLED out of $NM_LINES) found in $DM_OUTPUT:"
grep '^_Z' "$DM_OUTPUT"
die "Mangled symbols ($MANGLED out of $NM_LINES) found in $DM_OUTPUT"
fi
# All C++ symbols are demangled successfully.
echo "PASS"
exit 0

View file

@ -0,0 +1,145 @@
# Test caces for demangle_unittest. Each line consists of a
# tab-separated pair of mangled and demangled symbol names.
# Constructors and destructors.
_ZN3FooC1Ev Foo::Foo()
_ZN3FooD1Ev Foo::~Foo()
_ZNSoD0Ev std::ostream::~ostream()
# G++ extensions.
_ZTCN10LogMessage9LogStreamE0_So LogMessage::LogStream
_ZTv0_n12_N10LogMessage9LogStreamD0Ev LogMessage::LogStream::~LogStream()
_ZThn4_N7icu_3_410UnicodeSetD0Ev icu_3_4::UnicodeSet::~UnicodeSet()
# A bug in g++'s C++ ABI version 2 (-fabi-version=2).
_ZN7NSSInfoI5groupjjXadL_Z10getgrgid_rEELZ19nss_getgrgid_r_nameEEC1Ei NSSInfo<>::NSSInfo()
# C linkage symbol names. Should keep them untouched.
main main
Demangle Demangle
_ZERO _ZERO
# Cast operator.
_Zcviv operator int()
_ZN3foocviEv foo::operator int()
# Versioned symbols.
_Z3Foo@GLIBCXX_3.4 Foo@GLIBCXX_3.4
_Z3Foo@@GLIBCXX_3.4 Foo@@GLIBCXX_3.4
# Abbreviations.
_ZNSaE std::allocator
_ZNSbE std::basic_string
_ZNSdE std::iostream
_ZNSiE std::istream
_ZNSoE std::ostream
_ZNSsE std::string
# Substitutions. We just replace them with ?.
_ZN3fooS_E foo::?
_ZN3foo3barS0_E foo::bar::?
_ZNcvT_IiEEv operator ?<>()
# "<< <" case.
_ZlsI3fooE operator<< <>
# ABI tags.
_Z1AB3barB3foo A
_ZN3fooL3barB5cxx11E foo::bar
# Random things we found interesting.
_ZN3FooISt6vectorISsSaISsEEEclEv Foo<>::operator()()
_ZTI9Callback1IiE Callback1<>
_ZN7icu_3_47UMemorynwEj icu_3_4::UMemory::operator new()
_ZNSt6vectorIbE9push_backE std::vector<>::push_back
_ZNSt6vectorIbSaIbEE9push_backEb std::vector<>::push_back()
_ZlsRSoRK15PRIVATE_Counter operator<<()
_ZSt6fill_nIPPN9__gnu_cxx15_Hashtable_nodeISt4pairIKPKcjEEEjS8_ET_SA_T0_RKT1_ std::fill_n<>()
_ZZ3FoovE3Bar Foo()::Bar
_ZGVZ7UpTimervE8up_timer UpTimer()::up_timer
# Test cases from gcc-4.1.0/libstdc++-v3/testsuite/demangle.
# Collected by:
# % grep verify_demangle **/*.cc | perl -nle 'print $1 if /"(_Z.*?)"/' |
# sort | uniq
#
# Note that the following symbols are invalid.
# That's why they are not demangled.
# - _ZNZN1N1fEiE1X1gE
# - _ZNZN1N1fEiE1X1gEv
# - _Z1xINiEE
_Z1fA37_iPS_ f()
_Z1fAszL_ZZNK1N1A1fEvE3foo_0E_i f()
_Z1fI1APS0_PKS0_EvT_T0_T1_PA4_S3_M1CS8_ f<>()
_Z1fI1XENT_1tES2_ f<>()
_Z1fI1XEvPVN1AIT_E1TE f<>()
_Z1fILi1ELc120EEv1AIXplT_cviLd4028ae147ae147aeEEE f<>()
_Z1fILi1ELc120EEv1AIXplT_cviLf3f800000EEE f<>()
_Z1fILi5E1AEvN1CIXqugtT_Li0ELi1ELi2EEE1qE f<>()
_Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE f<>()
_Z1fILi5EEvN1AIXcvimlT_Li22EEE1qE f<>()
_Z1fIiEvi f<>()
_Z1fKPFiiE f()
_Z1fM1AFivEPS0_ f()
_Z1fM1AKFivE f()
_Z1fM1AKFvvE f()
_Z1fPFPA1_ivE f()
_Z1fPFYPFiiEiE f()
_Z1fPFvvEM1SFvvE f()
_Z1fPKM1AFivE f()
_Z1fi f()
_Z1fv f()
_Z1jM1AFivEPS1_ j()
_Z1rM1GFivEMS_KFivES_M1HFivES1_4whatIKS_E5what2IS8_ES3_ r()
_Z1sPA37_iPS0_ s()
_Z1xINiEE _Z1xINiEE
_Z3absILi11EEvv abs<>()
_Z3foo3bar foo()
_Z3foo5Hello5WorldS0_S_ foo()
_Z3fooA30_A_i foo()
_Z3fooIA6_KiEvA9_KT_rVPrS4_ foo<>()
_Z3fooILi2EEvRAplT_Li1E_i foo<>()
_Z3fooIiFvdEiEvv foo<>()
_Z3fooPM2ABi foo()
_Z3fooc foo()
_Z3fooiPiPS_PS0_PS1_PS2_PS3_PS4_PS5_PS6_PS7_PS8_PS9_PSA_PSB_PSC_ foo()
_Z3kooPA28_A30_i koo()
_Z4makeI7FactoryiET_IT0_Ev make<>()
_Z5firstI3DuoEvS0_ first<>()
_Z5firstI3DuoEvT_ first<>()
_Z9hairyfuncM1YKFPVPFrPA2_PM1XKFKPA3_ilEPcEiE hairyfunc()
_ZGVN5libcw24_GLOBAL__N_cbll.cc0ZhUKa23compiler_bug_workaroundISt6vectorINS_13omanip_id_tctINS_5debug32memblk_types_manipulator_data_ctEEESaIS6_EEE3idsE libcw::(anonymous namespace)::compiler_bug_workaround<>::ids
_ZN12libcw_app_ct10add_optionIS_EEvMT_FvPKcES3_cS3_S3_ libcw_app_ct::add_option<>()
_ZN1AIfEcvT_IiEEv A<>::operator ?<>()
_ZN1N1TIiiE2mfES0_IddE N::T<>::mf()
_ZN1N1fE N::f
_ZN1f1fE f::f
_ZN3FooIA4_iE3barE Foo<>::bar
_ZN5Arena5levelE Arena::level
_ZN5StackIiiE5levelE Stack<>::level
_ZN5libcw5debug13cwprint_usingINS_9_private_12GlobalObjectEEENS0_17cwprint_using_tctIT_EERKS5_MS5_KFvRSt7ostreamE libcw::debug::cwprint_using<>()
_ZN6System5Sound4beepEv System::Sound::beep()
_ZNKSt14priority_queueIP27timer_event_request_base_ctSt5dequeIS1_SaIS1_EE13timer_greaterE3topEv std::priority_queue<>::top()
_ZNKSt15_Deque_iteratorIP15memory_block_stRKS1_PS2_EeqERKS5_ std::_Deque_iterator<>::operator==()
_ZNKSt17__normal_iteratorIPK6optionSt6vectorIS0_SaIS0_EEEmiERKS6_ std::__normal_iterator<>::operator-()
_ZNSbIcSt11char_traitsIcEN5libcw5debug27no_alloc_checking_allocatorEE12_S_constructIPcEES6_T_S7_RKS3_ std::basic_string<>::_S_construct<>()
_ZNSt13_Alloc_traitsISbIcSt18string_char_traitsIcEN5libcw5debug9_private_17allocator_adaptorIcSt24__default_alloc_templateILb0ELi327664EELb1EEEENS5_IS9_S7_Lb1EEEE15_S_instancelessE std::_Alloc_traits<>::_S_instanceless
_ZNSt3_In4wardE std::_In::ward
_ZNZN1N1fEiE1X1gE _ZNZN1N1fEiE1X1gE
_ZNZN1N1fEiE1X1gEv _ZNZN1N1fEiE1X1gEv
_ZSt1BISt1DIP1ARKS2_PS3_ES0_IS2_RS2_PS2_ES2_ET0_T_SB_SA_PT1_ std::B<>()
_ZSt5state std::state
_ZTI7a_class a_class
_ZZN1N1fEiE1p N::f()::p
_ZZN1N1fEiEs N::f()
_ZlsRK1XS1_ operator<<()
_ZlsRKU3fooU4bart1XS0_ operator<<()
_ZlsRKU3fooU4bart1XS2_ operator<<()
_ZlsRSoRKSs operator<<()
_ZngILi42EEvN1AIXplT_Li2EEE1TE operator-<>()
_ZplR1XS0_ operator+()
_Zrm1XS_ operator%()
# Template argument packs can start with I or J.
_Z3addIIiEEvDpT_ add<>()
_Z3addIJiEEvDpT_ add<>()

107
third_party/glog/src/glog/log_severity.h vendored Normal file
View file

@ -0,0 +1,107 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_LOG_SEVERITY_H__
#define BASE_LOG_SEVERITY_H__
// The recommended semantics of the log levels are as follows:
//
// INFO:
// Use for state changes or other major events, or to aid debugging.
// WARNING:
// Use for undesired but relatively expected events, which may indicate a
// problem
// ERROR:
// Use for undesired and unexpected events that the program can recover from.
// All ERRORs should be actionable - it should be appropriate to file a bug
// whenever an ERROR occurs in production.
// FATAL:
// Use for undesired and unexpected events that the program cannot recover
// from.
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
// Variables of type LogSeverity are widely taken to lie in the range
// [0, NUM_SEVERITIES-1]. Be careful to preserve this assumption if
// you ever need to change their values or add a new severity.
typedef int LogSeverity;
const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
NUM_SEVERITIES = 4;
#ifndef GLOG_NO_ABBREVIATED_SEVERITIES
# ifdef ERROR
# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
# endif
const int INFO = GLOG_INFO, WARNING = GLOG_WARNING,
ERROR = GLOG_ERROR, FATAL = GLOG_FATAL;
#endif
// DFATAL is FATAL in debug mode, ERROR in normal mode
#ifdef NDEBUG
#define DFATAL_LEVEL ERROR
#else
#define DFATAL_LEVEL FATAL
#endif
extern GOOGLE_GLOG_DLL_DECL const char* const LogSeverityNames[NUM_SEVERITIES];
// NDEBUG usage helpers related to (RAW_)DCHECK:
//
// DEBUG_MODE is for small !NDEBUG uses like
// if (DEBUG_MODE) foo.CheckThatFoo();
// instead of substantially more verbose
// #ifndef NDEBUG
// foo.CheckThatFoo();
// #endif
//
// IF_DEBUG_MODE is for small !NDEBUG uses like
// IF_DEBUG_MODE( string error; )
// DCHECK(Foo(&error)) << error;
// instead of substantially more verbose
// #ifndef NDEBUG
// string error;
// DCHECK(Foo(&error)) << error;
// #endif
//
#ifdef NDEBUG
enum { DEBUG_MODE = 0 };
#define IF_DEBUG_MODE(x)
#else
enum { DEBUG_MODE = 1 };
#define IF_DEBUG_MODE(x) x
#endif
#endif // BASE_LOG_SEVERITY_H__

1689
third_party/glog/src/glog/logging.h.in vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,180 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Maxim Lifantsev
//
// Thread-safe logging routines that do not allocate any memory or
// acquire any locks, and can therefore be used by low-level memory
// allocation and synchronization code.
#ifndef BASE_RAW_LOGGING_H_
#define BASE_RAW_LOGGING_H_
#include <time.h>
@ac_google_start_namespace@
#include "glog/log_severity.h"
#include "glog/vlog_is_on.h"
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
// This is similar to LOG(severity) << format... and VLOG(level) << format..,
// but
// * it is to be used ONLY by low-level modules that can't use normal LOG()
// * it is desiged to be a low-level logger that does not allocate any
// memory and does not need any locks, hence:
// * it logs straight and ONLY to STDERR w/o buffering
// * it uses an explicit format and arguments list
// * it will silently chop off really long message strings
// Usage example:
// RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
// RAW_VLOG(3, "status is %i", status);
// These will print an almost standard log lines like this to stderr only:
// E20200821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
// I20200821 211317 file.cc:142] RAW: status is 20
#define RAW_LOG(severity, ...) \
do { \
switch (@ac_google_namespace@::GLOG_ ## severity) { \
case 0: \
RAW_LOG_INFO(__VA_ARGS__); \
break; \
case 1: \
RAW_LOG_WARNING(__VA_ARGS__); \
break; \
case 2: \
RAW_LOG_ERROR(__VA_ARGS__); \
break; \
case 3: \
RAW_LOG_FATAL(__VA_ARGS__); \
break; \
default: \
break; \
} \
} while (0)
// The following STRIP_LOG testing is performed in the header file so that it's
// possible to completely compile out the logging code and the log messages.
#if STRIP_LOG == 0
#define RAW_VLOG(verboselevel, ...) \
do { \
if (VLOG_IS_ON(verboselevel)) { \
RAW_LOG_INFO(__VA_ARGS__); \
} \
} while (0)
#else
#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
#if STRIP_LOG == 0
#define RAW_LOG_INFO(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_INFO, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_INFO(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
#if STRIP_LOG <= 1
#define RAW_LOG_WARNING(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_WARNING, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_WARNING(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 1
#if STRIP_LOG <= 2
#define RAW_LOG_ERROR(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_ERROR, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_ERROR(...) @ac_google_namespace@::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 2
#if STRIP_LOG <= 3
#define RAW_LOG_FATAL(...) @ac_google_namespace@::RawLog__(@ac_google_namespace@::GLOG_FATAL, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_FATAL(...) \
do { \
@ac_google_namespace@::RawLogStub__(0, __VA_ARGS__); \
exit(1); \
} while (0)
#endif // STRIP_LOG <= 3
// Similar to CHECK(condition) << message,
// but for low-level modules: we use only RAW_LOG that does not allocate memory.
// We do not want to provide args list here to encourage this usage:
// if (!cond) RAW_LOG(FATAL, "foo ...", hard_to_compute_args);
// so that the args are not computed when not needed.
#define RAW_CHECK(condition, message) \
do { \
if (!(condition)) { \
RAW_LOG(FATAL, "Check %s failed: %s", #condition, message); \
} \
} while (0)
// Debug versions of RAW_LOG and RAW_CHECK
#ifndef NDEBUG
#define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__)
#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message)
#else // NDEBUG
#define RAW_DLOG(severity, ...) \
while (false) \
RAW_LOG(severity, __VA_ARGS__)
#define RAW_DCHECK(condition, message) \
while (false) \
RAW_CHECK(condition, message)
#endif // NDEBUG
// Stub log function used to work around for unused variable warnings when
// building with STRIP_LOG > 0.
static inline void RawLogStub__(int /* ignored */, ...) {
}
// Helper function to implement RAW_LOG and RAW_VLOG
// Logs format... at "severity" level, reporting it
// as called from file:line.
// This does not allocate memory or acquire locks.
GOOGLE_GLOG_DLL_DECL void RawLog__(LogSeverity severity,
const char* file,
int line,
const char* format, ...)
@ac_cv___attribute___printf_4_5@;
@ac_google_end_namespace@
#endif // BASE_RAW_LOGGING_H_

View file

@ -0,0 +1,220 @@
// Copyright (c) 2003, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Stream output operators for STL containers; to be used for logging *only*.
// Inclusion of this file lets you do:
//
// list<string> x;
// LOG(INFO) << "data: " << x;
// vector<int> v1, v2;
// CHECK_EQ(v1, v2);
//
// If you want to use this header file with hash maps or slist, you
// need to define macros before including this file:
//
// - GLOG_STL_LOGGING_FOR_UNORDERED - <unordered_map> and <unordered_set>
// - GLOG_STL_LOGGING_FOR_TR1_UNORDERED - <tr1/unordered_(map|set)>
// - GLOG_STL_LOGGING_FOR_EXT_HASH - <ext/hash_(map|set)>
// - GLOG_STL_LOGGING_FOR_EXT_SLIST - <ext/slist>
//
#ifndef UTIL_GTL_STL_LOGGING_INL_H_
#define UTIL_GTL_STL_LOGGING_INL_H_
#if !@ac_cv_cxx_using_operator@
# error We do not support stl_logging for this compiler
#endif
#include <deque>
#include <list>
#include <map>
#include <ostream>
#include <set>
#include <utility>
#include <vector>
#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
# include <unordered_map>
# include <unordered_set>
#endif
#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
# include <tr1/unordered_map>
# include <tr1/unordered_set>
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
# include <ext/hash_set>
# include <ext/hash_map>
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
# include <ext/slist>
#endif
// Forward declare these two, and define them after all the container streams
// operators so that we can recurse from pair -> container -> container -> pair
// properly.
template<class First, class Second>
std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
@ac_google_start_namespace@
template<class Iter>
void PrintSequence(std::ostream& out, Iter begin, Iter end);
@ac_google_end_namespace@
#define OUTPUT_TWO_ARG_CONTAINER(Sequence) \
template<class T1, class T2> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2>& seq) { \
@ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
OUTPUT_TWO_ARG_CONTAINER(std::vector)
OUTPUT_TWO_ARG_CONTAINER(std::deque)
OUTPUT_TWO_ARG_CONTAINER(std::list)
#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
OUTPUT_TWO_ARG_CONTAINER(__gnu_cxx::slist)
#endif
#undef OUTPUT_TWO_ARG_CONTAINER
#define OUTPUT_THREE_ARG_CONTAINER(Sequence) \
template<class T1, class T2, class T3> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2, T3>& seq) { \
@ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
OUTPUT_THREE_ARG_CONTAINER(std::set)
OUTPUT_THREE_ARG_CONTAINER(std::multiset)
#undef OUTPUT_THREE_ARG_CONTAINER
#define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \
template<class T1, class T2, class T3, class T4> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2, T3, T4>& seq) { \
@ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
OUTPUT_FOUR_ARG_CONTAINER(std::map)
OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
OUTPUT_FOUR_ARG_CONTAINER(std::unordered_set)
OUTPUT_FOUR_ARG_CONTAINER(std::unordered_multiset)
#endif
#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_set)
OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_multiset)
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_set)
OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_multiset)
#endif
#undef OUTPUT_FOUR_ARG_CONTAINER
#define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \
template<class T1, class T2, class T3, class T4, class T5> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2, T3, T4, T5>& seq) { \
@ac_google_namespace@::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
OUTPUT_FIVE_ARG_CONTAINER(std::unordered_map)
OUTPUT_FIVE_ARG_CONTAINER(std::unordered_multimap)
#endif
#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_map)
OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_multimap)
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_map)
OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_multimap)
#endif
#undef OUTPUT_FIVE_ARG_CONTAINER
template<class First, class Second>
inline std::ostream& operator<<(std::ostream& out,
const std::pair<First, Second>& p) {
out << '(' << p.first << ", " << p.second << ')';
return out;
}
@ac_google_start_namespace@
template<class Iter>
inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
// Output at most 100 elements -- appropriate if used for logging.
for (int i = 0; begin != end && i < 100; ++i, ++begin) {
if (i > 0) out << ' ';
out << *begin;
}
if (begin != end) {
out << " ...";
}
}
@ac_google_end_namespace@
// Note that this is technically undefined behavior! We are adding things into
// the std namespace for a reason though -- we are providing new operations on
// types which are themselves defined with this namespace. Without this, these
// operator overloads cannot be found via ADL. If these definitions are not
// found via ADL, they must be #included before they're used, which requires
// this header to be included before apparently independent other headers.
//
// For example, base/logging.h defines various template functions to implement
// CHECK_EQ(x, y) and stream x and y into the log in the event the check fails.
// It does so via the function template MakeCheckOpValueString:
// template<class T>
// void MakeCheckOpValueString(strstream* ss, const T& v) {
// (*ss) << v;
// }
// Because 'glog/logging.h' is included before 'glog/stl_logging.h',
// subsequent CHECK_EQ(v1, v2) for vector<...> typed variable v1 and v2 can only
// find these operator definitions via ADL.
//
// Even this solution has problems -- it may pull unintended operators into the
// namespace as well, allowing them to also be found via ADL, and creating code
// that only works with a particular order of includes. Long term, we need to
// move all of the *definitions* into namespace std, bet we need to ensure no
// one references them first. This lets us take that step. We cannot define them
// in both because that would create ambiguous overloads when both are found.
namespace std { using ::operator<<; }
#endif // UTIL_GTL_STL_LOGGING_INL_H_

View file

@ -0,0 +1,129 @@
// Copyright (c) 1999, 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Ray Sidney and many others
//
// Defines the VLOG_IS_ON macro that controls the variable-verbosity
// conditional logging.
//
// It's used by VLOG and VLOG_IF in logging.h
// and by RAW_VLOG in raw_logging.h to trigger the logging.
//
// It can also be used directly e.g. like this:
// if (VLOG_IS_ON(2)) {
// // do some logging preparation and logging
// // that can't be accomplished e.g. via just VLOG(2) << ...;
// }
//
// The truth value that VLOG_IS_ON(level) returns is determined by
// the three verbosity level flags:
// --v=<n> Gives the default maximal active V-logging level;
// 0 is the default.
// Normally positive values are used for V-logging levels.
// --vmodule=<str> Gives the per-module maximal V-logging levels to override
// the value given by --v.
// E.g. "my_module=2,foo*=3" would change the logging level
// for all code in source files "my_module.*" and "foo*.*"
// ("-inl" suffixes are also disregarded for this matching).
//
// SetVLOGLevel helper function is provided to do limited dynamic control over
// V-logging by overriding the per-module settings given via --vmodule flag.
//
// CAVEAT: --vmodule functionality is not available in non gcc compilers.
//
#ifndef BASE_VLOG_IS_ON_H_
#define BASE_VLOG_IS_ON_H_
#include "glog/log_severity.h"
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
#if defined(__GNUC__)
// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site.
// (Normally) the first time every VLOG_IS_ON(n) site is hit,
// we determine what variable will dynamically control logging at this site:
// it's either FLAGS_v or an appropriate internal variable
// matching the current source file that represents results of
// parsing of --vmodule flag and/or SetVLOGLevel calls.
#define VLOG_IS_ON(verboselevel) \
__extension__ \
({ static @ac_google_namespace@::int32* vlocal__ = &@ac_google_namespace@::kLogSiteUninitialized; \
@ac_google_namespace@::int32 verbose_level__ = (verboselevel); \
(*vlocal__ >= verbose_level__) && \
((vlocal__ != &@ac_google_namespace@::kLogSiteUninitialized) || \
(@ac_google_namespace@::InitVLOG3__(&vlocal__, &FLAGS_v, \
__FILE__, verbose_level__))); })
#else
// GNU extensions not available, so we do not support --vmodule.
// Dynamic value of FLAGS_v always controls the logging level.
#define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel))
#endif
// Set VLOG(_IS_ON) level for module_pattern to log_level.
// This lets us dynamically control what is normally set by the --vmodule flag.
// Returns the level that previously applied to module_pattern.
// NOTE: To change the log level for VLOG(_IS_ON) sites
// that have already executed after/during InitGoogleLogging,
// one needs to supply the exact --vmodule pattern that applied to them.
// (If no --vmodule pattern applied to them
// the value of FLAGS_v will continue to control them.)
extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern,
int log_level);
// Various declarations needed for VLOG_IS_ON above: =========================
// Special value used to indicate that a VLOG_IS_ON site has not been
// initialized. We make this a large value, so the common-case check
// of "*vlocal__ >= verbose_level__" in VLOG_IS_ON definition
// passes in such cases and InitVLOG3__ is then triggered.
extern @ac_google_namespace@::int32 kLogSiteUninitialized;
// Helper routine which determines the logging info for a particalur VLOG site.
// site_flag is the address of the site-local pointer to the controlling
// verbosity level
// site_default is the default to use for *site_flag
// fname is the current source file name
// verbose_level is the argument to VLOG_IS_ON
// We will return the return value for VLOG_IS_ON
// and if possible set *site_flag appropriately.
extern GOOGLE_GLOG_DLL_DECL bool InitVLOG3__(
@ac_google_namespace@::int32** site_flag,
@ac_google_namespace@::int32* site_default,
const char* fname,
@ac_google_namespace@::int32 verbose_level);
#endif // BASE_VLOG_IS_ON_H_

611
third_party/glog/src/googletest.h vendored Normal file
View file

@ -0,0 +1,611 @@
// Copyright (c) 2009, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Shinichiro Hamaji
// (based on googletest: http://code.google.com/p/googletest/)
#ifdef GOOGLETEST_H__
#error You must not include this file twice.
#endif
#define GOOGLETEST_H__
#include "utilities.h"
#include <ctype.h>
#include <setjmp.h>
#include <time.h>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "base/commandlineflags.h"
using std::map;
using std::string;
using std::vector;
_START_GOOGLE_NAMESPACE_
extern GOOGLE_GLOG_DLL_DECL void (*g_logging_fail_func)();
_END_GOOGLE_NAMESPACE_
#undef GOOGLE_GLOG_DLL_DECL
#define GOOGLE_GLOG_DLL_DECL
static inline string GetTempDir() {
#ifndef OS_WINDOWS
return "/tmp";
#else
char tmp[MAX_PATH];
GetTempPathA(MAX_PATH, tmp);
return tmp;
#endif
}
#if defined(OS_WINDOWS) && defined(_MSC_VER) && !defined(TEST_SRC_DIR)
// The test will run in glog/vsproject/<project name>
// (e.g., glog/vsproject/logging_unittest).
static const char TEST_SRC_DIR[] = "../..";
#elif !defined(TEST_SRC_DIR)
# warning TEST_SRC_DIR should be defined in config.h
static const char TEST_SRC_DIR[] = ".";
#endif
static const uint32_t PTR_TEST_VALUE = 0x12345678;
DEFINE_string(test_tmpdir, GetTempDir(), "Dir we use for temp files");
DEFINE_string(test_srcdir, TEST_SRC_DIR,
"Source-dir root, needed to find glog_unittest_flagfile");
DEFINE_bool(run_benchmark, false, "If true, run benchmarks");
#ifdef NDEBUG
DEFINE_int32(benchmark_iters, 100000000, "Number of iterations per benchmark");
#else
DEFINE_int32(benchmark_iters, 100000, "Number of iterations per benchmark");
#endif
#ifdef HAVE_LIB_GTEST
# include <gtest/gtest.h>
// Use our ASSERT_DEATH implementation.
# undef ASSERT_DEATH
# undef ASSERT_DEBUG_DEATH
using testing::InitGoogleTest;
#else
_START_GOOGLE_NAMESPACE_
void InitGoogleTest(int*, char**);
void InitGoogleTest(int*, char**) {}
// The following is some bare-bones testing infrastructure
#define EXPECT_TRUE(cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "Check failed: %s\n", #cond); \
exit(1); \
} \
} while (0)
#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
#define EXPECT_OP(op, val1, val2) \
do { \
if (!((val1) op (val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
#define EXPECT_NAN(arg) \
do { \
if (!isnan(arg)) { \
fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#define EXPECT_INF(arg) \
do { \
if (!isinf(arg)) { \
fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#define EXPECT_DOUBLE_EQ(val1, val2) \
do { \
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_STREQ(val1, val2) \
do { \
if (strcmp((val1), (val2)) != 0) { \
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
exit(1); \
} \
} while (0)
vector<void (*)()> g_testlist; // the tests to run
#define TEST(a, b) \
struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { FlagSaver fs; RunTest(); } \
static void RunTest(); \
}; \
static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::RunTest()
static inline int RUN_ALL_TESTS() {
vector<void (*)()>::const_iterator it;
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
(*it)();
}
fprintf(stderr, "Passed %d tests\n\nPASS\n", (int)g_testlist.size());
return 0;
}
_END_GOOGLE_NAMESPACE_
#endif // ! HAVE_LIB_GTEST
_START_GOOGLE_NAMESPACE_
static bool g_called_abort;
static jmp_buf g_jmp_buf;
static inline void CalledAbort() {
g_called_abort = true;
longjmp(g_jmp_buf, 1);
}
#ifdef OS_WINDOWS
// TODO(hamaji): Death test somehow doesn't work in Windows.
#define ASSERT_DEATH(fn, msg)
#else
#define ASSERT_DEATH(fn, msg) \
do { \
g_called_abort = false; \
/* in logging.cc */ \
void (*original_logging_fail_func)() = g_logging_fail_func; \
g_logging_fail_func = &CalledAbort; \
if (!setjmp(g_jmp_buf)) fn; \
/* set back to their default */ \
g_logging_fail_func = original_logging_fail_func; \
if (!g_called_abort) { \
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
exit(1); \
} \
} while (0)
#endif
#ifdef NDEBUG
#define ASSERT_DEBUG_DEATH(fn, msg)
#else
#define ASSERT_DEBUG_DEATH(fn, msg) ASSERT_DEATH(fn, msg)
#endif // NDEBUG
// Benchmark tools.
#define BENCHMARK(n) static BenchmarkRegisterer __benchmark_ ## n (#n, &n);
map<string, void (*)(int)> g_benchlist; // the benchmarks to run
class BenchmarkRegisterer {
public:
BenchmarkRegisterer(const char* name, void (*function)(int iters)) {
EXPECT_TRUE(g_benchlist.insert(std::make_pair(name, function)).second);
}
};
static inline void RunSpecifiedBenchmarks() {
if (!FLAGS_run_benchmark) {
return;
}
int iter_cnt = FLAGS_benchmark_iters;
puts("Benchmark\tTime(ns)\tIterations");
for (map<string, void (*)(int)>::const_iterator iter = g_benchlist.begin();
iter != g_benchlist.end();
++iter) {
clock_t start = clock();
iter->second(iter_cnt);
double elapsed_ns =
((double)clock() - start) / CLOCKS_PER_SEC * 1000*1000*1000;
printf("%s\t%8.2lf\t%10d\n",
iter->first.c_str(), elapsed_ns / iter_cnt, iter_cnt);
}
puts("");
}
// ----------------------------------------------------------------------
// Golden file functions
// ----------------------------------------------------------------------
class CapturedStream {
public:
CapturedStream(int fd, const string & filename) :
fd_(fd),
uncaptured_fd_(-1),
filename_(filename) {
Capture();
}
~CapturedStream() {
if (uncaptured_fd_ != -1) {
CHECK(close(uncaptured_fd_) != -1);
}
}
// Start redirecting output to a file
void Capture() {
// Keep original stream for later
CHECK(uncaptured_fd_ == -1) << ", Stream " << fd_ << " already captured!";
uncaptured_fd_ = dup(fd_);
CHECK(uncaptured_fd_ != -1);
// Open file to save stream to
int cap_fd = open(filename_.c_str(),
O_CREAT | O_TRUNC | O_WRONLY,
S_IRUSR | S_IWUSR);
CHECK(cap_fd != -1);
// Send stdout/stderr to this file
fflush(NULL);
CHECK(dup2(cap_fd, fd_) != -1);
CHECK(close(cap_fd) != -1);
}
// Remove output redirection
void StopCapture() {
// Restore original stream
if (uncaptured_fd_ != -1) {
fflush(NULL);
CHECK(dup2(uncaptured_fd_, fd_) != -1);
}
}
const string & filename() const { return filename_; }
private:
int fd_; // file descriptor being captured
int uncaptured_fd_; // where the stream was originally being sent to
string filename_; // file where stream is being saved
};
static CapturedStream * s_captured_streams[STDERR_FILENO+1];
// Redirect a file descriptor to a file.
// fd - Should be STDOUT_FILENO or STDERR_FILENO
// filename - File where output should be stored
static inline void CaptureTestOutput(int fd, const string & filename) {
CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO));
CHECK(s_captured_streams[fd] == NULL);
s_captured_streams[fd] = new CapturedStream(fd, filename);
}
static inline void CaptureTestStderr() {
CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err");
}
// Return the size (in bytes) of a file
static inline size_t GetFileSize(FILE * file) {
fseek(file, 0, SEEK_END);
return static_cast<size_t>(ftell(file));
}
// Read the entire content of a file as a string
static inline string ReadEntireFile(FILE * file) {
const size_t file_size = GetFileSize(file);
char * const buffer = new char[file_size];
size_t bytes_last_read = 0; // # of bytes read in the last fread()
size_t bytes_read = 0; // # of bytes read so far
fseek(file, 0, SEEK_SET);
// Keep reading the file until we cannot read further or the
// pre-determined file size is reached.
do {
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
bytes_read += bytes_last_read;
} while (bytes_last_read > 0 && bytes_read < file_size);
const string content = string(buffer, buffer+bytes_read);
delete[] buffer;
return content;
}
// Get the captured stdout (when fd is STDOUT_FILENO) or stderr (when
// fd is STDERR_FILENO) as a string
static inline string GetCapturedTestOutput(int fd) {
CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO);
CapturedStream * const cap = s_captured_streams[fd];
CHECK(cap)
<< ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
// Make sure everything is flushed.
cap->StopCapture();
// Read the captured file.
FILE * const file = fopen(cap->filename().c_str(), "r");
const string content = ReadEntireFile(file);
fclose(file);
delete cap;
s_captured_streams[fd] = NULL;
return content;
}
// Get the captured stderr of a test as a string.
static inline string GetCapturedTestStderr() {
return GetCapturedTestOutput(STDERR_FILENO);
}
// Check if the string is [IWEF](\d{8}|YEARDATE)
static inline bool IsLoggingPrefix(const string& s) {
if (s.size() != 9) return false;
if (!strchr("IWEF", s[0])) return false;
for (int i = 1; i <= 8; ++i) {
if (!isdigit(s[i]) && s[i] != "YEARDATE"[i-1]) return false;
}
return true;
}
// Convert log output into normalized form.
//
// Example:
// I20200102 030405 logging_unittest.cc:345] RAW: vlog -1
// => IYEARDATE TIME__ logging_unittest.cc:LINE] RAW: vlog -1
static inline string MungeLine(const string& line) {
std::istringstream iss(line);
string before, logcode_date, time, thread_lineinfo;
iss >> logcode_date;
while (!IsLoggingPrefix(logcode_date)) {
before += " " + logcode_date;
if (!(iss >> logcode_date)) {
// We cannot find the header of log output.
return before;
}
}
if (!before.empty()) before += " ";
iss >> time;
iss >> thread_lineinfo;
CHECK(!thread_lineinfo.empty());
if (thread_lineinfo[thread_lineinfo.size() - 1] != ']') {
// We found thread ID.
string tmp;
iss >> tmp;
CHECK(!tmp.empty());
CHECK_EQ(']', tmp[tmp.size() - 1]);
thread_lineinfo = "THREADID " + tmp;
}
size_t index = thread_lineinfo.find(':');
CHECK_NE(string::npos, index);
thread_lineinfo = thread_lineinfo.substr(0, index+1) + "LINE]";
string rest;
std::getline(iss, rest);
return (before + logcode_date[0] + "YEARDATE TIME__ " + thread_lineinfo +
MungeLine(rest));
}
static inline void StringReplace(string* str,
const string& oldsub,
const string& newsub) {
size_t pos = str->find(oldsub);
if (pos != string::npos) {
str->replace(pos, oldsub.size(), newsub.c_str());
}
}
static inline string Munge(const string& filename) {
FILE* fp = fopen(filename.c_str(), "rb");
CHECK(fp != NULL) << filename << ": couldn't open";
char buf[4096];
string result;
while (fgets(buf, 4095, fp)) {
string line = MungeLine(buf);
char null_str[256];
char ptr_str[256];
sprintf(null_str, "%p", static_cast<void*>(NULL));
sprintf(ptr_str, "%p", reinterpret_cast<void*>(PTR_TEST_VALUE));
StringReplace(&line, "__NULLP__", null_str);
StringReplace(&line, "__PTRTEST__", ptr_str);
StringReplace(&line, "__SUCCESS__", StrError(0));
StringReplace(&line, "__ENOENT__", StrError(ENOENT));
StringReplace(&line, "__EINTR__", StrError(EINTR));
StringReplace(&line, "__ENXIO__", StrError(ENXIO));
StringReplace(&line, "__ENOEXEC__", StrError(ENOEXEC));
result += line + "\n";
}
fclose(fp);
return result;
}
static inline void WriteToFile(const string& body, const string& file) {
FILE* fp = fopen(file.c_str(), "wb");
fwrite(body.data(), 1, body.size(), fp);
fclose(fp);
}
static inline bool MungeAndDiffTestStderr(const string& golden_filename) {
CapturedStream* cap = s_captured_streams[STDERR_FILENO];
CHECK(cap) << ": did you forget CaptureTestStderr()?";
cap->StopCapture();
// Run munge
const string captured = Munge(cap->filename());
const string golden = Munge(golden_filename);
if (captured != golden) {
fprintf(stderr,
"Test with golden file failed. We'll try to show the diff:\n");
string munged_golden = golden_filename + ".munged";
WriteToFile(golden, munged_golden);
string munged_captured = cap->filename() + ".munged";
WriteToFile(captured, munged_captured);
#ifdef OS_WINDOWS
string diffcmd("fc " + munged_golden + " " + munged_captured);
#else
string diffcmd("diff -u " + munged_golden + " " + munged_captured);
#endif
if (system(diffcmd.c_str()) != 0) {
fprintf(stderr, "diff command was failed.\n");
}
unlink(munged_golden.c_str());
unlink(munged_captured.c_str());
return false;
}
LOG(INFO) << "Diff was successful";
return true;
}
// Save flags used from logging_unittest.cc.
#ifndef HAVE_LIB_GFLAGS
struct FlagSaver {
FlagSaver()
: v_(FLAGS_v),
stderrthreshold_(FLAGS_stderrthreshold),
logtostderr_(FLAGS_logtostderr),
alsologtostderr_(FLAGS_alsologtostderr) {}
~FlagSaver() {
FLAGS_v = v_;
FLAGS_stderrthreshold = stderrthreshold_;
FLAGS_logtostderr = logtostderr_;
FLAGS_alsologtostderr = alsologtostderr_;
}
int v_;
int stderrthreshold_;
bool logtostderr_;
bool alsologtostderr_;
};
#endif
class Thread {
public:
virtual ~Thread() {}
void SetJoinable(bool) {}
#if defined(OS_WINDOWS) && !defined(OS_CYGWIN)
void Start() {
handle_ = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)&Thread::InvokeThread,
(LPVOID)this,
0,
&th_);
CHECK(handle_) << "CreateThread";
}
void Join() {
WaitForSingleObject(handle_, INFINITE);
}
#elif defined(HAVE_PTHREAD)
void Start() {
pthread_create(&th_, NULL, &Thread::InvokeThread, this);
}
void Join() {
pthread_join(th_, NULL);
}
#else
# error No thread implementation.
#endif
protected:
virtual void Run() = 0;
private:
static void* InvokeThread(void* self) {
((Thread*)self)->Run();
return NULL;
}
#if defined(OS_WINDOWS) && !defined(OS_CYGWIN)
HANDLE handle_;
DWORD th_;
#else
pthread_t th_;
#endif
};
static inline void SleepForMilliseconds(int t) {
#ifndef OS_WINDOWS
# if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L
const struct timespec req = {0, t * 1000 * 1000};
nanosleep(&req, NULL);
# else
usleep(t * 1000);
# endif
#else
Sleep(t);
#endif
}
// Add hook for operator new to ensure there are no memory allocation.
void (*g_new_hook)() = NULL;
_END_GOOGLE_NAMESPACE_
void* operator new(size_t size) {
if (GOOGLE_NAMESPACE::g_new_hook) {
GOOGLE_NAMESPACE::g_new_hook();
}
return malloc(size);
}
void* operator new[](size_t size) {
return ::operator new(size);
}
void operator delete(void* p) {
free(p);
}
void operator delete[](void* p) {
::operator delete(p);
}

2344
third_party/glog/src/logging.cc vendored Normal file

File diff suppressed because it is too large Load diff

79
third_party/glog/src/logging_striplog_test.sh vendored Executable file
View file

@ -0,0 +1,79 @@
#! /bin/sh
#
# Copyright (c) 2007, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Sergey Ioffe
get_strings () {
if test -e ".libs/$1"; then
binary=".libs/$1"
elif test -e "$1.exe"; then
binary="$1.exe"
else
echo "We coundn't find $1 binary."
exit 1
fi
strings -n 10 $binary | sort | awk '/TESTMESSAGE/ {printf "%s ", $2}'
}
# Die if "$1" != "$2", print $3 as death reason
check_eq () {
if [ "$1" != "$2" ]; then
echo "Check failed: '$1' == '$2' ${3:+ ($3)}"
exit 1
fi
}
die () {
echo $1
exit 1
}
# Check that the string literals are appropriately stripped. This will
# not be the case in debug mode.
mode=`GLOG_check_mode=1 ./logging_striptest0 2> /dev/null`
if [ "$mode" = "opt" ];
then
echo "In OPT mode"
check_eq "`get_strings logging_striptest0`" "COND ERROR FATAL INFO USAGE WARNING "
check_eq "`get_strings logging_striptest2`" "COND ERROR FATAL USAGE "
check_eq "`get_strings logging_striptest10`" ""
else
echo "In DBG mode; not checking strings"
fi
# Check that LOG(FATAL) aborts even for large STRIP_LOG
./logging_striptest2 2>/dev/null && die "Did not abort for STRIP_LOG=2"
./logging_striptest10 2>/dev/null && die "Did not abort for STRIP_LOG=10"
echo "PASS"

View file

@ -0,0 +1,35 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sergey Ioffe
#define GOOGLE_STRIP_LOG 10
// Include the actual test.
#include "logging_striptest_main.cc"

View file

@ -0,0 +1,35 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sergey Ioffe
#define GOOGLE_STRIP_LOG 2
// Include the actual test.
#include "logging_striptest_main.cc"

View file

@ -0,0 +1,73 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Sergey Ioffe
// The common part of the striplog tests.
#include <stdio.h>
#include <string>
#include <iosfwd>
#include "glog/logging.h"
#include "base/commandlineflags.h"
#include "config.h"
DECLARE_bool(logtostderr);
GLOG_DEFINE_bool(check_mode, false, "Prints 'opt' or 'dbg'");
using std::string;
using namespace GOOGLE_NAMESPACE;
int CheckNoReturn(bool b) {
string s;
if (b) {
LOG(FATAL) << "Fatal";
} else {
return 0;
}
}
struct A { };
std::ostream &operator<<(std::ostream &str, const A&) {return str;}
int main(int, char* argv[]) {
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
if (FLAGS_check_mode) {
printf("%s\n", DEBUG_MODE ? "dbg" : "opt");
return 0;
}
LOG(INFO) << "TESTMESSAGE INFO";
LOG(WARNING) << 2 << "something" << "TESTMESSAGE WARNING"
<< 1 << 'c' << A() << std::endl;
LOG(ERROR) << "TESTMESSAGE ERROR";
bool flag = true;
(flag ? LOG(INFO) : LOG(ERROR)) << "TESTMESSAGE COND";
LOG(FATAL) << "TESTMESSAGE FATAL";
}

1348
third_party/glog/src/logging_unittest.cc vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,307 @@
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
WARNING: Logging before InitGoogleLogging() is written to STDERR
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] foo bar 10 3.4
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 1: __SUCCESS__ [0]
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 1
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 1
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 1
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 2
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 3: __ENOENT__ [2]
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 3
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if less than 3 every 2, iteration 3
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 4
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 4
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 5: __EINTR__ [4]
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 5
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 5
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 5, iteration 6
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 6
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 7: __ENXIO__ [6]
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 7
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 7
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 8
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Plog every 2, iteration 9: __ENOEXEC__ [8]
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 4, iteration 9
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 9
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log every 3, iteration 10
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Log if every 1, iteration 10
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if this
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] array
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] const array
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] foo 1000 0000001000 3e8
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] inner
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] outer
no prefix
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo bar 10 3.400000
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: array
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: const array
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr __PTRTEST__
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: ptr __NULLP__
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000 0000001000 3e8
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo 1000
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: RAW_LOG ERROR: The Message was too long!
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0 on
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1 on
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 2 on
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=0 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=-1 stderrthreshold=0 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=1 logtostderr=0 alsologtostderr=0
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=2 logtostderr=0 alsologtostderr=0
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=1 alsologtostderr=0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=0 stderrthreshold=3 logtostderr=0 alsologtostderr=1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=1 logtostderr=0 alsologtostderr=0
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Test: v=1 stderrthreshold=3 logtostderr=0 alsologtostderr=1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: vlog 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if -1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if info every 1 expr
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] log_if error every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] vlog_if 0 every 1 expr
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_STRING: reported error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected info
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected warning
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_STRING: LOG_STRING: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: reported error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_SINK:
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_SINK_BUT_NOT_TO_LOGFILE: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected info
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected warning
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Captured by LOG_TO_STRING: LOG_TO_STRING: collected error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported info
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported warning
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] LOG_TO_STRING: reported error
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffering
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Buffered
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waiting
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Sink got a messages
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: Waited
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink is sending out a message: WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Have 0 left
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 1
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: EYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 2
IYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Sink capture: WYEARDATE TIME__ THREADID logging_unittest.cc:LINE] Message 3

156
third_party/glog/src/mock-log.h vendored Normal file
View file

@ -0,0 +1,156 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Zhanyong Wan
//
// Defines the ScopedMockLog class (using Google C++ Mocking
// Framework), which is convenient for testing code that uses LOG().
#ifndef GLOG_SRC_MOCK_LOG_H_
#define GLOG_SRC_MOCK_LOG_H_
// For GOOGLE_NAMESPACE. This must go first so we get _XOPEN_SOURCE.
#include "utilities.h"
#include <string>
#include <gmock/gmock.h>
#include "glog/logging.h"
_START_GOOGLE_NAMESPACE_
namespace glog_testing {
// A ScopedMockLog object intercepts LOG() messages issued during its
// lifespan. Using this together with Google C++ Mocking Framework,
// it's very easy to test how a piece of code calls LOG(). The
// typical usage:
//
// TEST(FooTest, LogsCorrectly) {
// ScopedMockLog log;
//
// // We expect the WARNING "Something bad!" exactly twice.
// EXPECT_CALL(log, Log(WARNING, _, "Something bad!"))
// .Times(2);
//
// // We allow foo.cc to call LOG(INFO) any number of times.
// EXPECT_CALL(log, Log(INFO, HasSubstr("/foo.cc"), _))
// .Times(AnyNumber());
//
// Foo(); // Exercises the code under test.
// }
class ScopedMockLog : public GOOGLE_NAMESPACE::LogSink {
public:
// When a ScopedMockLog object is constructed, it starts to
// intercept logs.
ScopedMockLog() { AddLogSink(this); }
// When the object is destructed, it stops intercepting logs.
virtual ~ScopedMockLog() { RemoveLogSink(this); }
// Implements the mock method:
//
// void Log(LogSeverity severity, const string& file_path,
// const string& message);
//
// The second argument to Send() is the full path of the source file
// in which the LOG() was issued.
//
// Note, that in a multi-threaded environment, all LOG() messages from a
// single thread will be handled in sequence, but that cannot be guaranteed
// for messages from different threads. In fact, if the same or multiple
// expectations are matched on two threads concurrently, their actions will
// be executed concurrently as well and may interleave.
MOCK_METHOD3(Log, void(GOOGLE_NAMESPACE::LogSeverity severity,
const std::string& file_path,
const std::string& message));
private:
// Implements the send() virtual function in class LogSink.
// Whenever a LOG() statement is executed, this function will be
// invoked with information presented in the LOG().
//
// The method argument list is long and carries much information a
// test usually doesn't care about, so we trim the list before
// forwarding the call to Log(), which is much easier to use in
// tests.
//
// We still cannot call Log() directly, as it may invoke other LOG()
// messages, either due to Invoke, or due to an error logged in
// Google C++ Mocking Framework code, which would trigger a deadlock
// since a lock is held during send().
//
// Hence, we save the message for WaitTillSent() which will be called after
// the lock on send() is released, and we'll call Log() inside
// WaitTillSent(). Since while a single send() call may be running at a
// time, multiple WaitTillSent() calls (along with the one send() call) may
// be running simultaneously, we ensure thread-safety of the exchange between
// send() and WaitTillSent(), and that for each message, LOG(), send(),
// WaitTillSent() and Log() are executed in the same thread.
virtual void send(GOOGLE_NAMESPACE::LogSeverity severity,
const char* full_filename,
const char* /*base_filename*/, int /*line*/,
const tm* /*tm_time*/,
const char* message, size_t message_len) {
// We are only interested in the log severity, full file name, and
// log message.
message_info_.severity = severity;
message_info_.file_path = full_filename;
message_info_.message = std::string(message, message_len);
}
// Implements the WaitTillSent() virtual function in class LogSink.
// It will be executed after send() and after the global logging lock is
// released, so calls within it (or rather within the Log() method called
// within) may also issue LOG() statements.
//
// LOG(), send(), WaitTillSent() and Log() will occur in the same thread for
// a given log message.
virtual void WaitTillSent() {
// First, and very importantly, we save a copy of the message being
// processed before calling Log(), since Log() may indirectly call send()
// and WaitTillSent() in the same thread again.
MessageInfo message_info = message_info_;
Log(message_info.severity, message_info.file_path, message_info.message);
}
// All relevant information about a logged message that needs to be passed
// from send() to WaitTillSent().
struct MessageInfo {
GOOGLE_NAMESPACE::LogSeverity severity;
std::string file_path;
std::string message;
};
MessageInfo message_info_;
};
} // namespace glog_testing
_END_GOOGLE_NAMESPACE_
#endif // GLOG_SRC_MOCK_LOG_H_

106
third_party/glog/src/mock-log_test.cc vendored Normal file
View file

@ -0,0 +1,106 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Zhanyong Wan
// Tests the ScopedMockLog class.
#include "mock-log.h"
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace {
using GOOGLE_NAMESPACE::INFO;
using GOOGLE_NAMESPACE::WARNING;
using GOOGLE_NAMESPACE::ERROR;
using GOOGLE_NAMESPACE::glog_testing::ScopedMockLog;
using std::string;
using testing::_;
using testing::HasSubstr;
using testing::InSequence;
using testing::InvokeWithoutArgs;
// Tests that ScopedMockLog intercepts LOG()s when it's alive.
TEST(ScopedMockLogTest, InterceptsLog) {
ScopedMockLog log;
InSequence s;
EXPECT_CALL(log, Log(WARNING, HasSubstr("/mock-log_test.cc"), "Fishy."));
EXPECT_CALL(log, Log(INFO, _, "Working..."))
.Times(2);
EXPECT_CALL(log, Log(ERROR, _, "Bad!!"));
LOG(WARNING) << "Fishy.";
LOG(INFO) << "Working...";
LOG(INFO) << "Working...";
LOG(ERROR) << "Bad!!";
}
void LogBranch() {
LOG(INFO) << "Logging a branch...";
}
void LogTree() {
LOG(INFO) << "Logging the whole tree...";
}
void LogForest() {
LOG(INFO) << "Logging the entire forest.";
LOG(INFO) << "Logging the entire forest..";
LOG(INFO) << "Logging the entire forest...";
}
// The purpose of the following test is to verify that intercepting logging
// continues to work properly if a LOG statement is executed within the scope
// of a mocked call.
TEST(ScopedMockLogTest, LogDuringIntercept) {
ScopedMockLog log;
InSequence s;
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging a branch..."))
.WillOnce(InvokeWithoutArgs(LogTree));
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the whole tree..."))
.WillOnce(InvokeWithoutArgs(LogForest));
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest."));
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest.."));
EXPECT_CALL(log, Log(INFO, __FILE__, "Logging the entire forest..."));
LogBranch();
}
} // namespace
int main(int argc, char **argv) {
GOOGLE_NAMESPACE::InitGoogleLogging(argv[0]);
testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}

View file

@ -0,0 +1,8 @@
cmake_minimum_required (VERSION 3.1)
project (glog_package_config)
find_package (glog REQUIRED NO_MODULE)
add_executable (glog_package_config glog_package_config.cc)
target_link_libraries (glog_package_config PRIVATE glog::glog)

View file

@ -0,0 +1,6 @@
#include <glog/logging.h>
int main(int /*argc*/, char** argv)
{
google::InitGoogleLogging(argv[0]);
}

158
third_party/glog/src/raw_logging.cc vendored Normal file
View file

@ -0,0 +1,158 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Maxim Lifantsev
//
// logging_unittest.cc covers the functionality herein
#include "utilities.h"
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h> // for close() and write()
#endif
#include <fcntl.h> // for open()
#include <time.h>
#include "config.h"
#include "glog/logging.h" // To pick up flag settings etc.
#include "glog/raw_logging.h"
#include "base/commandlineflags.h"
#ifdef HAVE_STACKTRACE
# include "stacktrace.h"
#endif
#if defined(HAVE_SYSCALL_H)
#include <syscall.h> // for syscall()
#elif defined(HAVE_SYS_SYSCALL_H)
#include <sys/syscall.h> // for syscall()
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)
# define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
#else
// Not so safe, but what can you do?
# define safe_write(fd, s, len) write(fd, s, len)
#endif
_START_GOOGLE_NAMESPACE_
// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
// that invoke malloc() and getenv() that might acquire some locks.
// If this becomes a problem we should reimplement a subset of vsnprintf
// that does not need locks and malloc.
// Helper for RawLog__ below.
// *DoRawLog writes to *buf of *size and move them past the written portion.
// It returns true iff there was no overflow or error.
static bool DoRawLog(char** buf, int* size, const char* format, ...) {
va_list ap;
va_start(ap, format);
int n = vsnprintf(*buf, *size, format, ap);
va_end(ap);
if (n < 0 || n > *size) return false;
*size -= n;
*buf += n;
return true;
}
// Helper for RawLog__ below.
inline static bool VADoRawLog(char** buf, int* size,
const char* format, va_list ap) {
int n = vsnprintf(*buf, *size, format, ap);
if (n < 0 || n > *size) return false;
*size -= n;
*buf += n;
return true;
}
static const int kLogBufSize = 3000;
static bool crashed = false;
static CrashReason crash_reason;
static char crash_buf[kLogBufSize + 1] = { 0 }; // Will end in '\0'
void RawLog__(LogSeverity severity, const char* file, int line,
const char* format, ...) {
if (!(FLAGS_logtostderr || severity >= FLAGS_stderrthreshold ||
FLAGS_alsologtostderr || !IsGoogleLoggingInitialized())) {
return; // this stderr log message is suppressed
}
// can't call localtime_r here: it can allocate
char buffer[kLogBufSize];
char* buf = buffer;
int size = sizeof(buffer);
// NOTE: this format should match the specification in base/logging.h
DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %5u %s:%d] RAW: ",
LogSeverityNames[severity][0],
static_cast<unsigned int>(GetTID()),
const_basename(const_cast<char *>(file)), line);
// Record the position and size of the buffer after the prefix
const char* msg_start = buf;
const int msg_size = size;
va_list ap;
va_start(ap, format);
bool no_chop = VADoRawLog(&buf, &size, format, ap);
va_end(ap);
if (no_chop) {
DoRawLog(&buf, &size, "\n");
} else {
DoRawLog(&buf, &size, "RAW_LOG ERROR: The Message was too long!\n");
}
// We make a raw syscall to write directly to the stderr file descriptor,
// avoiding FILE buffering (to avoid invoking malloc()), and bypassing
// libc (to side-step any libc interception).
// We write just once to avoid races with other invocations of RawLog__.
safe_write(STDERR_FILENO, buffer, strlen(buffer));
if (severity == GLOG_FATAL) {
if (!sync_val_compare_and_swap(&crashed, false, true)) {
crash_reason.filename = file;
crash_reason.line_number = line;
memcpy(crash_buf, msg_start, msg_size); // Don't include prefix
crash_reason.message = crash_buf;
#ifdef HAVE_STACKTRACE
crash_reason.depth =
GetStackTrace(crash_reason.stack, ARRAYSIZE(crash_reason.stack), 1);
#else
crash_reason.depth = 0;
#endif
SetCrashReason(&crash_reason);
}
LogMessage::Fail(); // abort()
}
}
_END_GOOGLE_NAMESPACE_

403
third_party/glog/src/signalhandler.cc vendored Normal file
View file

@ -0,0 +1,403 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// Implementation of InstallFailureSignalHandler().
#include "utilities.h"
#include "stacktrace.h"
#include "symbolize.h"
#include "glog/logging.h"
#include <signal.h>
#include <time.h>
#ifdef HAVE_UCONTEXT_H
# include <ucontext.h>
#endif
#ifdef HAVE_SYS_UCONTEXT_H
# include <sys/ucontext.h>
#endif
#include <algorithm>
_START_GOOGLE_NAMESPACE_
namespace {
// We'll install the failure signal handler for these signals. We could
// use strsignal() to get signal names, but we don't use it to avoid
// introducing yet another #ifdef complication.
//
// The list should be synced with the comment in signalhandler.h.
const struct {
int number;
const char *name;
} kFailureSignals[] = {
{ SIGSEGV, "SIGSEGV" },
{ SIGILL, "SIGILL" },
{ SIGFPE, "SIGFPE" },
{ SIGABRT, "SIGABRT" },
#if !defined(OS_WINDOWS)
{ SIGBUS, "SIGBUS" },
#endif
{ SIGTERM, "SIGTERM" },
};
static bool kFailureSignalHandlerInstalled = false;
// Returns the program counter from signal context, NULL if unknown.
void* GetPC(void* ucontext_in_void) {
#if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT)
if (ucontext_in_void != NULL) {
ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
return (void*)context->PC_FROM_UCONTEXT;
}
#endif
return NULL;
}
// The class is used for formatting error messages. We don't use printf()
// as it's not async signal safe.
class MinimalFormatter {
public:
MinimalFormatter(char *buffer, int size)
: buffer_(buffer),
cursor_(buffer),
end_(buffer + size) {
}
// Returns the number of bytes written in the buffer.
int num_bytes_written() const { return (int) (cursor_ - buffer_); }
// Appends string from "str" and updates the internal cursor.
void AppendString(const char* str) {
int i = 0;
while (str[i] != '\0' && cursor_ + i < end_) {
cursor_[i] = str[i];
++i;
}
cursor_ += i;
}
// Formats "number" in "radix" and updates the internal cursor.
// Lowercase letters are used for 'a' - 'z'.
void AppendUint64(uint64 number, int radix) {
int i = 0;
while (cursor_ + i < end_) {
const int tmp = number % radix;
number /= radix;
cursor_[i] = (tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
++i;
if (number == 0) {
break;
}
}
// Reverse the bytes written.
std::reverse(cursor_, cursor_ + i);
cursor_ += i;
}
// Formats "number" as hexadecimal number, and updates the internal
// cursor. Padding will be added in front if needed.
void AppendHexWithPadding(uint64 number, int width) {
char* start = cursor_;
AppendString("0x");
AppendUint64(number, 16);
// Move to right and add padding in front if needed.
if (cursor_ < start + width) {
const int64 delta = start + width - cursor_;
std::copy(start, cursor_, start + delta);
std::fill(start, start + delta, ' ');
cursor_ = start + width;
}
}
private:
char *buffer_;
char *cursor_;
const char * const end_;
};
// Writes the given data with the size to the standard error.
void WriteToStderr(const char* data, int size) {
if (write(STDERR_FILENO, data, size) < 0) {
// Ignore errors.
}
}
// The writer function can be changed by InstallFailureWriter().
void (*g_failure_writer)(const char* data, int size) = WriteToStderr;
// Dumps time information. We don't dump human-readable time information
// as localtime() is not guaranteed to be async signal safe.
void DumpTimeInfo() {
time_t time_in_sec = time(NULL);
char buf[256]; // Big enough for time info.
MinimalFormatter formatter(buf, sizeof(buf));
formatter.AppendString("*** Aborted at ");
formatter.AppendUint64(time_in_sec, 10);
formatter.AppendString(" (unix time)");
formatter.AppendString(" try \"date -d @");
formatter.AppendUint64(time_in_sec, 10);
formatter.AppendString("\" if you are using GNU date ***\n");
g_failure_writer(buf, formatter.num_bytes_written());
}
// TODO(hamaji): Use signal instead of sigaction?
#ifdef HAVE_SIGACTION
// Dumps information about the signal to STDERR.
void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
// Get the signal name.
const char* signal_name = NULL;
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
if (signal_number == kFailureSignals[i].number) {
signal_name = kFailureSignals[i].name;
}
}
char buf[256]; // Big enough for signal info.
MinimalFormatter formatter(buf, sizeof(buf));
formatter.AppendString("*** ");
if (signal_name) {
formatter.AppendString(signal_name);
} else {
// Use the signal number if the name is unknown. The signal name
// should be known, but just in case.
formatter.AppendString("Signal ");
formatter.AppendUint64(signal_number, 10);
}
formatter.AppendString(" (@0x");
formatter.AppendUint64(reinterpret_cast<uintptr_t>(siginfo->si_addr), 16);
formatter.AppendString(")");
formatter.AppendString(" received by PID ");
formatter.AppendUint64(getpid(), 10);
formatter.AppendString(" (TID 0x");
// We assume pthread_t is an integral number or a pointer, rather
// than a complex struct. In some environments, pthread_self()
// returns an uint64 but in some other environments pthread_self()
// returns a pointer. Hence we use C-style cast here, rather than
// reinterpret/static_cast, to support both types of environments.
formatter.AppendUint64((uintptr_t)pthread_self(), 16);
formatter.AppendString(") ");
// Only linux has the PID of the signal sender in si_pid.
#ifdef OS_LINUX
formatter.AppendString("from PID ");
formatter.AppendUint64(siginfo->si_pid, 10);
formatter.AppendString("; ");
#endif
formatter.AppendString("stack trace: ***\n");
g_failure_writer(buf, formatter.num_bytes_written());
}
#endif // HAVE_SIGACTION
// Dumps information about the stack frame to STDERR.
void DumpStackFrameInfo(const char* prefix, void* pc) {
// Get the symbol name.
const char *symbol = "(unknown)";
char symbolized[1024]; // Big enough for a sane symbol.
// Symbolizes the previous address of pc because pc may be in the
// next function.
if (Symbolize(reinterpret_cast<char *>(pc) - 1,
symbolized, sizeof(symbolized))) {
symbol = symbolized;
}
char buf[1024]; // Big enough for stack frame info.
MinimalFormatter formatter(buf, sizeof(buf));
formatter.AppendString(prefix);
formatter.AppendString("@ ");
const int width = 2 * sizeof(void*) + 2; // + 2 for "0x".
formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
formatter.AppendString(" ");
formatter.AppendString(symbol);
formatter.AppendString("\n");
g_failure_writer(buf, formatter.num_bytes_written());
}
// Invoke the default signal handler.
void InvokeDefaultSignalHandler(int signal_number) {
#ifdef HAVE_SIGACTION
struct sigaction sig_action;
memset(&sig_action, 0, sizeof(sig_action));
sigemptyset(&sig_action.sa_mask);
sig_action.sa_handler = SIG_DFL;
sigaction(signal_number, &sig_action, NULL);
kill(getpid(), signal_number);
#elif defined(OS_WINDOWS)
signal(signal_number, SIG_DFL);
raise(signal_number);
#endif
}
// This variable is used for protecting FailureSignalHandler() from
// dumping stuff while another thread is doing it. Our policy is to let
// the first thread dump stuff and let other threads wait.
// See also comments in FailureSignalHandler().
static pthread_t* g_entered_thread_id_pointer = NULL;
// Dumps signal and stack frame information, and invokes the default
// signal handler once our job is done.
#if defined(OS_WINDOWS)
void FailureSignalHandler(int signal_number)
#else
void FailureSignalHandler(int signal_number,
siginfo_t *signal_info,
void *ucontext)
#endif
{
// First check if we've already entered the function. We use an atomic
// compare and swap operation for platforms that support it. For other
// platforms, we use a naive method that could lead to a subtle race.
// We assume pthread_self() is async signal safe, though it's not
// officially guaranteed.
pthread_t my_thread_id = pthread_self();
// NOTE: We could simply use pthread_t rather than pthread_t* for this,
// if pthread_self() is guaranteed to return non-zero value for thread
// ids, but there is no such guarantee. We need to distinguish if the
// old value (value returned from __sync_val_compare_and_swap) is
// different from the original value (in this case NULL).
pthread_t* old_thread_id_pointer =
glog_internal_namespace_::sync_val_compare_and_swap(
&g_entered_thread_id_pointer,
static_cast<pthread_t*>(NULL),
&my_thread_id);
if (old_thread_id_pointer != NULL) {
// We've already entered the signal handler. What should we do?
if (pthread_equal(my_thread_id, *g_entered_thread_id_pointer)) {
// It looks the current thread is reentering the signal handler.
// Something must be going wrong (maybe we are reentering by another
// type of signal?). Kill ourself by the default signal handler.
InvokeDefaultSignalHandler(signal_number);
}
// Another thread is dumping stuff. Let's wait until that thread
// finishes the job and kills the process.
while (true) {
sleep(1);
}
}
// This is the first time we enter the signal handler. We are going to
// do some interesting stuff from here.
// TODO(satorux): We might want to set timeout here using alarm(), but
// mixing alarm() and sleep() can be a bad idea.
// First dump time info.
DumpTimeInfo();
#if !defined(OS_WINDOWS)
// Get the program counter from ucontext.
void *pc = GetPC(ucontext);
DumpStackFrameInfo("PC: ", pc);
#endif
#ifdef HAVE_STACKTRACE
// Get the stack traces.
void *stack[32];
// +1 to exclude this function.
const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1);
# ifdef HAVE_SIGACTION
DumpSignalInfo(signal_number, signal_info);
# endif
// Dump the stack traces.
for (int i = 0; i < depth; ++i) {
DumpStackFrameInfo(" ", stack[i]);
}
#endif
// *** TRANSITION ***
//
// BEFORE this point, all code must be async-termination-safe!
// (See WARNING above.)
//
// AFTER this point, we do unsafe things, like using LOG()!
// The process could be terminated or hung at any time. We try to
// do more useful things first and riskier things later.
// Flush the logs before we do anything in case 'anything'
// causes problems.
FlushLogFilesUnsafe(0);
// Kill ourself by the default signal handler.
InvokeDefaultSignalHandler(signal_number);
}
} // namespace
namespace glog_internal_namespace_ {
bool IsFailureSignalHandlerInstalled() {
#ifdef HAVE_SIGACTION
// TODO(andschwa): Return kFailureSignalHandlerInstalled?
struct sigaction sig_action;
memset(&sig_action, 0, sizeof(sig_action));
sigemptyset(&sig_action.sa_mask);
sigaction(SIGABRT, NULL, &sig_action);
if (sig_action.sa_sigaction == &FailureSignalHandler)
return true;
#elif defined(OS_WINDOWS)
return kFailureSignalHandlerInstalled;
#endif // HAVE_SIGACTION
return false;
}
} // namespace glog_internal_namespace_
void InstallFailureSignalHandler() {
#ifdef HAVE_SIGACTION
// Build the sigaction struct.
struct sigaction sig_action;
memset(&sig_action, 0, sizeof(sig_action));
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags |= SA_SIGINFO;
sig_action.sa_sigaction = &FailureSignalHandler;
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
}
kFailureSignalHandlerInstalled = true;
#elif defined(OS_WINDOWS)
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
CHECK_NE(signal(kFailureSignals[i].number, &FailureSignalHandler),
SIG_ERR);
}
kFailureSignalHandlerInstalled = true;
#endif // HAVE_SIGACTION
}
void InstallFailureWriter(void (*writer)(const char* data, int size)) {
#if defined(HAVE_SIGACTION) || defined(OS_WINDOWS)
g_failure_writer = writer;
#endif // HAVE_SIGACTION
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,112 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// This is a helper binary for testing signalhandler.cc. The actual test
// is done in signalhandler_unittest.sh.
#include "utilities.h"
#if defined(HAVE_PTHREAD)
# include <pthread.h>
#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "glog/logging.h"
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE;
#endif
using namespace GOOGLE_NAMESPACE;
static void* DieInThread(void*) {
// We assume pthread_t is an integral number or a pointer, rather
// than a complex struct. In some environments, pthread_self()
// returns an uint64 but in some other environments pthread_self()
// returns a pointer. Hence we use C-style cast here, rather than
// reinterpret/static_cast, to support both types of environments.
fprintf(stderr, "0x%lx is dying\n", (long)pthread_self());
// Use volatile to prevent from these to be optimized away.
volatile int a = 0;
volatile int b = 1 / a;
fprintf(stderr, "We should have died: b=%d\n", b);
return NULL;
}
static void WriteToStdout(const char* data, int size) {
if (write(STDOUT_FILENO, data, size) < 0) {
// Ignore errors.
}
}
int main(int argc, char **argv) {
#if defined(HAVE_STACKTRACE) && defined(HAVE_SYMBOLIZE)
InitGoogleLogging(argv[0]);
#ifdef HAVE_LIB_GFLAGS
ParseCommandLineFlags(&argc, &argv, true);
#endif
InstallFailureSignalHandler();
const std::string command = argc > 1 ? argv[1] : "none";
if (command == "segv") {
// We'll check if this is outputted.
LOG(INFO) << "create the log file";
LOG(INFO) << "a message before segv";
// We assume 0xDEAD is not writable.
int *a = (int*)0xDEAD;
*a = 0;
} else if (command == "loop") {
fprintf(stderr, "looping\n");
while (true);
} else if (command == "die_in_thread") {
#if defined(HAVE_PTHREAD)
pthread_t thread;
pthread_create(&thread, NULL, &DieInThread, NULL);
pthread_join(thread, NULL);
#else
fprintf(stderr, "no pthread\n");
return 1;
#endif
} else if (command == "dump_to_stdout") {
InstallFailureWriter(WriteToStdout);
abort();
} else if (command == "installed") {
fprintf(stderr, "signal handler installed: %s\n",
IsFailureSignalHandlerInstalled() ? "true" : "false");
} else {
// Tell the shell script
puts("OK");
}
#endif
return 0;
}

131
third_party/glog/src/signalhandler_unittest.sh vendored Executable file
View file

@ -0,0 +1,131 @@
#! /bin/sh
#
# Copyright (c) 2008, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Satoru Takabayashi
#
# Unit tests for signalhandler.cc.
die () {
echo $1
exit 1
}
BINDIR=".libs"
LIBGLOG="$BINDIR/libglog.so"
BINARY="$BINDIR/signalhandler_unittest"
LOG_INFO="./signalhandler_unittest.INFO"
# Remove temporary files.
rm -f signalhandler.out*
if test -e "$BINARY"; then
# We need shared object.
export LD_LIBRARY_PATH=$BINDIR
export DYLD_LIBRARY_PATH=$BINDIR
else
# For windows
BINARY="./signalhandler_unittest.exe"
if ! test -e "$BINARY"; then
echo "We coundn't find demangle_unittest binary."
exit 1
fi
fi
if [ x`$BINARY` != 'xOK' ]; then
echo "PASS (No stacktrace support. We don't run this test.)"
exit 0
fi
# The PC cannot be obtained in signal handlers on PowerPC correctly.
# We just skip the test for PowerPC.
if [ x`uname -p` = x"powerpc" ]; then
echo "PASS (We don't test the signal handler on PowerPC.)"
exit 0
fi
# Test for a case the program kills itself by SIGSEGV.
GOOGLE_LOG_DIR=. $BINARY segv 2> signalhandler.out1
for pattern in SIGSEGV 0xdead main "Aborted at [0-9]"; do
if ! grep --quiet "$pattern" signalhandler.out1; then
die "'$pattern' should appear in the output"
fi
done
if ! grep --quiet "a message before segv" $LOG_INFO; then
die "'a message before segv' should appear in the INFO log"
fi
rm -f $LOG_INFO
# Test for a case the program is killed by this shell script.
# $! = the process id of the last command run in the background.
# $$ = the process id of this shell.
$BINARY loop 2> signalhandler.out2 &
# Wait until "looping" is written in the file. This indicates the program
# is ready to accept signals.
while true; do
if grep --quiet looping signalhandler.out2; then
break
fi
done
kill -TERM $!
wait $!
from_pid=''
# Only linux has the process ID of the signal sender.
if [ x`uname` = "xLinux" ]; then
from_pid="from PID $$"
fi
for pattern in SIGTERM "by PID $!" "$from_pid" main "Aborted at [0-9]"; do
if ! grep --quiet "$pattern" signalhandler.out2; then
die "'$pattern' should appear in the output"
fi
done
# Test for a case the program dies in a non-main thread.
$BINARY die_in_thread 2> signalhandler.out3
EXPECTED_TID="`sed 's/ .*//; q' signalhandler.out3`"
for pattern in SIGFPE DieInThread "TID $EXPECTED_TID" "Aborted at [0-9]"; do
if ! grep --quiet "$pattern" signalhandler.out3; then
die "'$pattern' should appear in the output"
fi
done
# Test for a case the program installs a custom failure writer that writes
# stuff to stdout instead of stderr.
$BINARY dump_to_stdout 1> signalhandler.out4
for pattern in SIGABRT main "Aborted at [0-9]"; do
if ! grep --quiet "$pattern" signalhandler.out4; then
die "'$pattern' should appear in the output"
fi
done
echo PASS

61
third_party/glog/src/stacktrace.h vendored Normal file
View file

@ -0,0 +1,61 @@
// Copyright (c) 2000 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Routines to extract the current stack trace. These functions are
// thread-safe.
#ifndef BASE_STACKTRACE_H_
#define BASE_STACKTRACE_H_
#include "config.h"
#include "glog/logging.h"
_START_GOOGLE_NAMESPACE_
// This is similar to the GetStackFrames routine, except that it returns
// the stack trace only, and not the stack frame sizes as well.
// Example:
// main() { foo(); }
// foo() { bar(); }
// bar() {
// void* result[10];
// int depth = GetStackFrames(result, 10, 1);
// }
//
// This produces:
// result[0] foo
// result[1] main
// .... ...
//
// "result" must not be NULL.
GOOGLE_GLOG_DLL_DECL int GetStackTrace(void** result, int max_depth, int skip_count);
_END_GOOGLE_NAMESPACE_
#endif // BASE_STACKTRACE_H_

View file

@ -0,0 +1,59 @@
// Copyright (c) 2000 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Portable implementation - just use glibc
//
// Note: The glibc implementation may cause a call to malloc.
// This can cause a deadlock in HeapProfiler.
#include <execinfo.h>
#include <string.h>
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
static const int kStackLength = 64;
void * stack[kStackLength];
int size;
size = backtrace(stack, kStackLength);
skip_count++; // we want to skip the current frame as well
int result_count = size - skip_count;
if (result_count < 0)
result_count = 0;
if (result_count > max_depth)
result_count = max_depth;
for (int i = 0; i < result_count; i++)
result[i] = stack[i + skip_count];
return result_count;
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,90 @@
// Copyright (c) 2005 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Arun Sharma
//
// Produce stack trace using libunwind
#include "utilities.h"
extern "C" {
#define UNW_LOCAL_ONLY
#include <libunwind.h>
}
#include "glog/raw_logging.h"
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
// Sometimes, we can try to get a stack trace from within a stack
// trace, because libunwind can call mmap (maybe indirectly via an
// internal mmap based memory allocator), and that mmap gets trapped
// and causes a stack-trace request. If were to try to honor that
// recursive request, we'd end up with infinite recursion or deadlock.
// Luckily, it's safe to ignore those subsequent traces. In such
// cases, we return 0 to indicate the situation.
// We can use the GCC __thread syntax here since libunwind is not supported on
// Windows.
static __thread bool g_tl_entered; // Initialized to false.
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
void *ip;
int n = 0;
unw_cursor_t cursor;
unw_context_t uc;
if (g_tl_entered) {
return 0;
}
g_tl_entered = true;
unw_getcontext(&uc);
RAW_CHECK(unw_init_local(&cursor, &uc) >= 0, "unw_init_local failed");
skip_count++; // Do not include the "GetStackTrace" frame
while (n < max_depth) {
int ret = unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip);
if (ret < 0)
break;
if (skip_count > 0) {
skip_count--;
} else {
result[n++] = ip;
}
ret = unw_step(&cursor);
if (ret <= 0)
break;
}
g_tl_entered = false;
return n;
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,130 @@
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Craig Silverstein
//
// Produce stack trace. I'm guessing (hoping!) the code is much like
// for x86. For apple machines, at least, it seems to be; see
// http://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
// Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882
#include <stdio.h>
#include <stdint.h> // for uintptr_t
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
// Given a pointer to a stack frame, locate and return the calling
// stackframe, or return NULL if no stackframe can be found. Perform sanity
// checks (the strictness of which is controlled by the boolean parameter
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING>
static void **NextStackFrame(void **old_sp) {
void **new_sp = (void **) *old_sp;
// Check that the transition from frame pointer old_sp to frame
// pointer new_sp isn't clearly bogus
if (STRICT_UNWINDING) {
// With the stack growing downwards, older stack frame must be
// at a greater address that the current one.
if (new_sp <= old_sp) return NULL;
// Assume stack frames larger than 100,000 bytes are bogus.
if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
} else {
// In the non-strict mode, allow discontiguous stack frames.
// (alternate-signal-stacks for example).
if (new_sp == old_sp) return NULL;
// And allow frames upto about 1MB.
if ((new_sp > old_sp)
&& ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
}
if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
return new_sp;
}
// This ensures that GetStackTrace stes up the Link Register properly.
void StacktracePowerPCDummyFunction() __attribute__((noinline));
void StacktracePowerPCDummyFunction() { __asm__ volatile(""); }
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
void **sp;
// Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther)
// and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a
// different asm syntax. I don't know quite the best way to discriminate
// systems using the old as from the new one; I've gone with __APPLE__.
#ifdef __APPLE__
__asm__ volatile ("mr %0,r1" : "=r" (sp));
#else
__asm__ volatile ("mr %0,1" : "=r" (sp));
#endif
// On PowerPC, the "Link Register" or "Link Record" (LR), is a stack
// entry that holds the return address of the subroutine call (what
// instruction we run after our function finishes). This is the
// same as the stack-pointer of our parent routine, which is what we
// want here. While the compiler will always(?) set up LR for
// subroutine calls, it may not for leaf functions (such as this one).
// This routine forces the compiler (at least gcc) to push it anyway.
StacktracePowerPCDummyFunction();
// The LR save area is used by the callee, so the top entry is bogus.
skip_count++;
int n = 0;
while (sp && n < max_depth) {
if (skip_count > 0) {
skip_count--;
} else {
// PowerPC has 3 main ABIs, which say where in the stack the
// Link Register is. For DARWIN and AIX (used by apple and
// linux ppc64), it's in sp[2]. For SYSV (used by linux ppc),
// it's in sp[1].
#if defined(_CALL_AIX) || defined(_CALL_DARWIN)
result[n++] = *(sp+2);
#elif defined(_CALL_SYSV)
result[n++] = *(sp+1);
#elif defined(__APPLE__) || ((defined(__linux) || defined(__linux__)) && defined(__PPC64__))
// This check is in case the compiler doesn't define _CALL_AIX/etc.
result[n++] = *(sp+2);
#elif defined(__linux)
// This check is in case the compiler doesn't define _CALL_SYSV.
result[n++] = *(sp+1);
#else
#error Need to specify the PPC ABI for your archiecture.
#endif
}
// Use strict unwinding rules.
sp = NextStackFrame<true>(sp);
}
return n;
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,217 @@
// Copyright (c) 2004, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "utilities.h"
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "base/commandlineflags.h"
#include "glog/logging.h"
#include "stacktrace.h"
#ifdef HAVE_EXECINFO_H
# include <execinfo.h>
#endif
using namespace GOOGLE_NAMESPACE;
#ifdef HAVE_STACKTRACE
// Obtain a backtrace, verify that the expected callers are present in the
// backtrace, and maybe print the backtrace to stdout.
// The sequence of functions whose return addresses we expect to see in the
// backtrace.
const int BACKTRACE_STEPS = 6;
struct AddressRange {
const void *start, *end;
};
// Expected function [start,end] range.
AddressRange expected_range[BACKTRACE_STEPS];
#if __GNUC__
// Using GCC extension: address of a label can be taken with '&&label'.
// Start should be a label somewhere before recursive call, end somewhere
// after it.
#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
do { \
(prange)->start = &&start_label; \
(prange)->end = &&end_label; \
CHECK_LT((prange)->start, (prange)->end); \
} while (0)
// This macro expands into "unmovable" code (opaque to GCC), and that
// prevents GCC from moving a_label up or down in the code.
// Without it, there is no code following the 'end' label, and GCC
// (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before
// the recursive call.
#define DECLARE_ADDRESS_LABEL(a_label) \
a_label: do { __asm__ __volatile__(""); } while (0)
// Gcc 4.4.0 may split function into multiple chunks, and the chunk
// performing recursive call may end up later in the code then the return
// instruction (this actually happens with FDO).
// Adjust function range from __builtin_return_address.
#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
do { \
void *ra = __builtin_return_address(0); \
CHECK_LT((prange)->start, ra); \
if (ra > (prange)->end) { \
printf("Adjusting range from %p..%p to %p..%p\n", \
(prange)->start, (prange)->end, \
(prange)->start, ra); \
(prange)->end = ra; \
} \
} while (0)
#else
// Assume the Check* functions below are not longer than 256 bytes.
#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
do { \
(prange)->start = reinterpret_cast<const void *>(&fn); \
(prange)->end = reinterpret_cast<const char *>(&fn) + 256; \
} while (0)
#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0)
#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0)
#endif // __GNUC__
//-----------------------------------------------------------------------//
static void CheckRetAddrIsInFunction(void *ret_addr, const AddressRange &range)
{
CHECK_GE(ret_addr, range.start);
CHECK_LE(ret_addr, range.end);
}
//-----------------------------------------------------------------------//
void ATTRIBUTE_NOINLINE CheckStackTrace(int);
static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf(void) {
const int STACK_LEN = 10;
void *stack[STACK_LEN];
int size;
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]);
INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]);
DECLARE_ADDRESS_LABEL(start);
size = GetStackTrace(stack, STACK_LEN, 0);
printf("Obtained %d stack frames.\n", size);
CHECK_GE(size, 1);
CHECK_LE(size, STACK_LEN);
if (1) {
#ifdef HAVE_EXECINFO_H
char **strings = backtrace_symbols(stack, size);
printf("Obtained %d stack frames.\n", size);
for (int i = 0; i < size; i++)
printf("%s %p\n", strings[i], stack[i]);
printf("CheckStackTrace() addr: %p\n", &CheckStackTrace);
free(strings);
#endif
}
for (int i = 0; i < BACKTRACE_STEPS; i++) {
printf("Backtrace %d: expected: %p..%p actual: %p ... ",
i, expected_range[i].start, expected_range[i].end, stack[i]);
fflush(stdout);
CheckRetAddrIsInFunction(stack[i], expected_range[i]);
printf("OK\n");
}
DECLARE_ADDRESS_LABEL(end);
}
//-----------------------------------------------------------------------//
/* Dummy functions to make the backtrace more interesting. */
static void ATTRIBUTE_NOINLINE CheckStackTrace4(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[2]);
INIT_ADDRESS_RANGE(CheckStackTrace4, start, end, &expected_range[1]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTraceLeaf();
DECLARE_ADDRESS_LABEL(end);
}
static void ATTRIBUTE_NOINLINE CheckStackTrace3(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[3]);
INIT_ADDRESS_RANGE(CheckStackTrace3, start, end, &expected_range[2]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace4(j);
DECLARE_ADDRESS_LABEL(end);
}
static void ATTRIBUTE_NOINLINE CheckStackTrace2(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[4]);
INIT_ADDRESS_RANGE(CheckStackTrace2, start, end, &expected_range[3]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace3(j);
DECLARE_ADDRESS_LABEL(end);
}
static void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[5]);
INIT_ADDRESS_RANGE(CheckStackTrace1, start, end, &expected_range[4]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace2(j);
DECLARE_ADDRESS_LABEL(end);
}
#ifndef __GNUC__
// On non-GNU environment, we use the address of `CheckStackTrace` to
// guess the address range of this function. This guess is wrong for
// non-static function on Windows. This is probably because
// `&CheckStackTrace` returns the address of a trampoline like PLT,
// not the actual address of `CheckStackTrace`.
// See https://github.com/google/glog/issues/421 for the detail.
static
#endif
void ATTRIBUTE_NOINLINE CheckStackTrace(int i) {
INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]);
DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace1(j);
DECLARE_ADDRESS_LABEL(end);
}
//-----------------------------------------------------------------------//
int main(int, char ** argv) {
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
CheckStackTrace(0);
printf("PASS\n");
return 0;
}
#else
int main() {
printf("PASS (no stacktrace support)\n");
return 0;
}
#endif // HAVE_STACKTRACE

View file

@ -0,0 +1,50 @@
// Copyright (c) 2000 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Andrew Schwartzmeyer
//
// Windows implementation - just use CaptureStackBackTrace
#include "config.h"
#include "port.h"
#include "stacktrace.h"
#include <dbghelp.h>
_START_GOOGLE_NAMESPACE_
int GetStackTrace(void** result, int max_depth, int skip_count) {
if (max_depth > 64) {
max_depth = 64;
}
skip_count++; // we want to skip the current frame as well
// This API is thread-safe (moreover it walks only the current thread).
return CaptureStackBackTrace(skip_count, max_depth, result, NULL);
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,146 @@
// Copyright (c) 2000 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Produce stack trace
#include <stdint.h> // for uintptr_t
#include "utilities.h" // for OS_* macros
#if !defined(OS_WINDOWS)
#include <unistd.h>
#include <sys/mman.h>
#endif
#include <stdio.h> // for NULL
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
// Given a pointer to a stack frame, locate and return the calling
// stackframe, or return NULL if no stackframe can be found. Perform sanity
// checks (the strictness of which is controlled by the boolean parameter
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING>
static void **NextStackFrame(void **old_sp) {
void **new_sp = (void **) *old_sp;
// Check that the transition from frame pointer old_sp to frame
// pointer new_sp isn't clearly bogus
if (STRICT_UNWINDING) {
// With the stack growing downwards, older stack frame must be
// at a greater address that the current one.
if (new_sp <= old_sp) return NULL;
// Assume stack frames larger than 100,000 bytes are bogus.
if ((uintptr_t)new_sp - (uintptr_t)old_sp > 100000) return NULL;
} else {
// In the non-strict mode, allow discontiguous stack frames.
// (alternate-signal-stacks for example).
if (new_sp == old_sp) return NULL;
// And allow frames upto about 1MB.
if ((new_sp > old_sp)
&& ((uintptr_t)new_sp - (uintptr_t)old_sp > 1000000)) return NULL;
}
if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return NULL;
#ifdef __i386__
// On 64-bit machines, the stack pointer can be very close to
// 0xffffffff, so we explicitly check for a pointer into the
// last two pages in the address space
if ((uintptr_t)new_sp >= 0xffffe000) return NULL;
#endif
#if !defined(OS_WINDOWS)
if (!STRICT_UNWINDING) {
// Lax sanity checks cause a crash in 32-bit tcmalloc/crash_reason_test
// on AMD-based machines with VDSO-enabled kernels.
// Make an extra sanity check to insure new_sp is readable.
// Note: NextStackFrame<false>() is only called while the program
// is already on its last leg, so it's ok to be slow here.
static int page_size = getpagesize();
void *new_sp_aligned = (void *)((uintptr_t)new_sp & ~(page_size - 1));
if (msync(new_sp_aligned, page_size, MS_ASYNC) == -1)
return NULL;
}
#endif
return new_sp;
}
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
void **sp;
#ifdef __GNUC__
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 402
#define USE_BUILTIN_FRAME_ADDRESS
#endif
#endif
#ifdef USE_BUILTIN_FRAME_ADDRESS
sp = reinterpret_cast<void**>(__builtin_frame_address(0));
#elif defined(__i386__)
// Stack frame format:
// sp[0] pointer to previous frame
// sp[1] caller address
// sp[2] first argument
// ...
sp = (void **)&result - 2;
#elif defined(__x86_64__)
// __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8
unsigned long rbp;
// Move the value of the register %rbp into the local variable rbp.
// We need 'volatile' to prevent this instruction from getting moved
// around during optimization to before function prologue is done.
// An alternative way to achieve this
// would be (before this __asm__ instruction) to call Noop() defined as
// static void Noop() __attribute__ ((noinline)); // prevent inlining
// static void Noop() { asm(""); } // prevent optimizing-away
__asm__ volatile ("mov %%rbp, %0" : "=r" (rbp));
// Arguments are passed in registers on x86-64, so we can't just
// offset from &result
sp = (void **) rbp;
#endif
int n = 0;
while (sp && n < max_depth) {
if (*(sp+1) == (void *)0) {
// In 64-bit code, we often see a frame that
// points to itself and has a return address of 0.
break;
}
if (skip_count > 0) {
skip_count--;
} else {
result[n++] = *(sp+1);
}
// Use strict unwinding rules.
sp = NextStackFrame<true>(sp);
}
return n;
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,105 @@
// Copyright (c) 2005 - 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Arun Sharma
//
// Produce stack trace using libgcc
extern "C" {
#include <stdlib.h> // for NULL
#include <unwind.h> // ABI defined unwinder
}
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_
typedef struct {
void **result;
int max_depth;
int skip_count;
int count;
} trace_arg_t;
// Workaround for the malloc() in _Unwind_Backtrace() issue.
static _Unwind_Reason_Code nop_backtrace(struct _Unwind_Context *uc, void *opq) {
return _URC_NO_REASON;
}
// This code is not considered ready to run until
// static initializers run so that we are guaranteed
// that any malloc-related initialization is done.
static bool ready_to_run = false;
class StackTraceInit {
public:
StackTraceInit() {
// Extra call to force initialization
_Unwind_Backtrace(nop_backtrace, NULL);
ready_to_run = true;
}
};
static StackTraceInit module_initializer; // Force initialization
static _Unwind_Reason_Code GetOneFrame(struct _Unwind_Context *uc, void *opq) {
trace_arg_t *targ = (trace_arg_t *) opq;
if (targ->skip_count > 0) {
targ->skip_count--;
} else {
targ->result[targ->count++] = (void *) _Unwind_GetIP(uc);
}
if (targ->count == targ->max_depth)
return _URC_END_OF_STACK;
return _URC_NO_REASON;
}
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
if (!ready_to_run)
return 0;
trace_arg_t targ;
skip_count += 1; // Do not include the "GetStackTrace" frame
targ.result = result;
targ.max_depth = max_depth;
targ.skip_count = skip_count;
targ.count = 0;
_Unwind_Backtrace(GetOneFrame, &targ);
return targ.count;
}
_END_GOOGLE_NAMESPACE_

View file

@ -0,0 +1,197 @@
// Copyright (c) 2003, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
#ifdef HAVE_USING_OPERATOR
#include <functional>
#include <iostream>
#include <map>
#include <ostream>
#include <string>
#include <vector>
#ifdef __GNUC__
// C++0x isn't enabled by default in GCC and libc++ does not have
// non-standard ext/* and tr1/unordered_*.
# if defined(_LIBCPP_VERSION)
# ifndef GLOG_STL_LOGGING_FOR_UNORDERED
# define GLOG_STL_LOGGING_FOR_UNORDERED
# endif
# else
# ifndef GLOG_STL_LOGGING_FOR_EXT_HASH
# define GLOG_STL_LOGGING_FOR_EXT_HASH
# endif
# ifndef GLOG_STL_LOGGING_FOR_EXT_SLIST
# define GLOG_STL_LOGGING_FOR_EXT_SLIST
# endif
# ifndef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
# define GLOG_STL_LOGGING_FOR_TR1_UNORDERED
# endif
# endif
#endif
#include "glog/logging.h"
#include "glog/stl_logging.h"
#include "googletest.h"
using namespace std;
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
using namespace __gnu_cxx;
#endif
struct user_hash {
size_t operator()(int x) const { return x; }
};
static void TestSTLLogging() {
{
// Test a sequence.
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
ostringstream ss;
ss << v;
EXPECT_EQ(ss.str(), "10 20 30");
vector<int> copied_v(v);
CHECK_EQ(v, copied_v); // This must compile.
}
{
// Test a sorted pair associative container.
map< int, string > m;
m[20] = "twenty";
m[10] = "ten";
m[30] = "thirty";
ostringstream ss;
ss << m;
EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)");
map< int, string > copied_m(m);
CHECK_EQ(m, copied_m); // This must compile.
}
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
{
// Test a hashed simple associative container.
hash_set<int> hs;
hs.insert(10);
hs.insert(20);
hs.insert(30);
ostringstream ss;
ss << hs;
EXPECT_EQ(ss.str(), "10 20 30");
hash_set<int> copied_hs(hs);
CHECK_EQ(hs, copied_hs); // This must compile.
}
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
{
// Test a hashed pair associative container.
hash_map<int, string> hm;
hm[10] = "ten";
hm[20] = "twenty";
hm[30] = "thirty";
ostringstream ss;
ss << hm;
EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)");
hash_map<int, string> copied_hm(hm);
CHECK_EQ(hm, copied_hm); // this must compile
}
#endif
{
// Test a long sequence.
vector<int> v;
string expected;
for (int i = 0; i < 100; i++) {
v.push_back(i);
if (i > 0) expected += ' ';
char buf[256];
sprintf(buf, "%d", i);
expected += buf;
}
v.push_back(100);
expected += " ...";
ostringstream ss;
ss << v;
CHECK_EQ(ss.str(), expected.c_str());
}
{
// Test a sorted pair associative container.
// Use a non-default comparison functor.
map< int, string, greater<int> > m;
m[20] = "twenty";
m[10] = "ten";
m[30] = "thirty";
ostringstream ss;
ss << m;
EXPECT_EQ(ss.str(), "(30, thirty) (20, twenty) (10, ten)");
map< int, string, greater<int> > copied_m(m);
CHECK_EQ(m, copied_m); // This must compile.
}
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
{
// Test a hashed simple associative container.
// Use a user defined hash function.
hash_set<int, user_hash> hs;
hs.insert(10);
hs.insert(20);
hs.insert(30);
ostringstream ss;
ss << hs;
EXPECT_EQ(ss.str(), "10 20 30");
hash_set<int, user_hash> copied_hs(hs);
CHECK_EQ(hs, copied_hs); // This must compile.
}
#endif
}
int main(int, char**) {
TestSTLLogging();
std::cout << "PASS\n";
return 0;
}
#else
#include <iostream>
int main(int, char**) {
std::cout << "We don't support stl_logging for this compiler.\n"
<< "(we need compiler support of 'using ::operator<<' "
<< "for this feature.)\n";
return 0;
}
#endif // HAVE_USING_OPERATOR

966
third_party/glog/src/symbolize.cc vendored Normal file
View file

@ -0,0 +1,966 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
// Stack-footprint reduction work done by Raksit Ashok
//
// Implementation note:
//
// We don't use heaps but only use stacks. We want to reduce the
// stack consumption so that the symbolizer can run on small stacks.
//
// Here are some numbers collected with GCC 4.1.0 on x86:
// - sizeof(Elf32_Sym) = 16
// - sizeof(Elf32_Shdr) = 40
// - sizeof(Elf64_Sym) = 24
// - sizeof(Elf64_Shdr) = 64
//
// This implementation is intended to be async-signal-safe but uses
// some functions which are not guaranteed to be so, such as memchr()
// and memmove(). We assume they are async-signal-safe.
//
// Additional header can be specified by the GLOG_BUILD_CONFIG_INCLUDE
// macro to add platform specific defines (e.g. OS_OPENBSD).
#ifdef GLOG_BUILD_CONFIG_INCLUDE
#include GLOG_BUILD_CONFIG_INCLUDE
#endif // GLOG_BUILD_CONFIG_INCLUDE
#include "utilities.h"
#if defined(HAVE_SYMBOLIZE)
#include <string.h>
#include <algorithm>
#include <limits>
#include "symbolize.h"
#include "demangle.h"
_START_GOOGLE_NAMESPACE_
// We don't use assert() since it's not guaranteed to be
// async-signal-safe. Instead we define a minimal assertion
// macro. So far, we don't need pretty printing for __FILE__, etc.
// A wrapper for abort() to make it callable in ? :.
static int AssertFail() {
abort();
return 0; // Should not reach.
}
#define SAFE_ASSERT(expr) ((expr) ? 0 : AssertFail())
static SymbolizeCallback g_symbolize_callback = NULL;
void InstallSymbolizeCallback(SymbolizeCallback callback) {
g_symbolize_callback = callback;
}
static SymbolizeOpenObjectFileCallback g_symbolize_open_object_file_callback =
NULL;
void InstallSymbolizeOpenObjectFileCallback(
SymbolizeOpenObjectFileCallback callback) {
g_symbolize_open_object_file_callback = callback;
}
// This function wraps the Demangle function to provide an interface
// where the input symbol is demangled in-place.
// To keep stack consumption low, we would like this function to not
// get inlined.
static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, int out_size) {
char demangled[256]; // Big enough for sane demangled symbols.
if (Demangle(out, demangled, sizeof(demangled))) {
// Demangling succeeded. Copy to out if the space allows.
size_t len = strlen(demangled);
if (len + 1 <= (size_t)out_size) { // +1 for '\0'.
SAFE_ASSERT(len < sizeof(demangled));
memmove(out, demangled, len + 1);
}
}
}
_END_GOOGLE_NAMESPACE_
#if defined(__ELF__)
#if defined(HAVE_DLFCN_H)
#include <dlfcn.h>
#endif
#if defined(OS_OPENBSD)
#include <sys/exec_elf.h>
#else
#include <elf.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "symbolize.h"
#include "config.h"
#include "glog/raw_logging.h"
// Re-runs fn until it doesn't cause EINTR.
#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR)
_START_GOOGLE_NAMESPACE_
// Read up to "count" bytes from "offset" in the file pointed by file
// descriptor "fd" into the buffer starting at "buf" while handling short reads
// and EINTR. On success, return the number of bytes read. Otherwise, return
// -1.
static ssize_t ReadFromOffset(const int fd, void *buf, const size_t count,
const off_t offset) {
SAFE_ASSERT(fd >= 0);
SAFE_ASSERT(count <= std::numeric_limits<ssize_t>::max());
char *buf0 = reinterpret_cast<char *>(buf);
ssize_t num_bytes = 0;
while (num_bytes < count) {
ssize_t len;
NO_INTR(len = pread(fd, buf0 + num_bytes, count - num_bytes,
offset + num_bytes));
if (len < 0) { // There was an error other than EINTR.
return -1;
}
if (len == 0) { // Reached EOF.
break;
}
num_bytes += len;
}
SAFE_ASSERT(num_bytes <= count);
return num_bytes;
}
// Try reading exactly "count" bytes from "offset" bytes in a file
// pointed by "fd" into the buffer starting at "buf" while handling
// short reads and EINTR. On success, return true. Otherwise, return
// false.
static bool ReadFromOffsetExact(const int fd, void *buf,
const size_t count, const off_t offset) {
ssize_t len = ReadFromOffset(fd, buf, count, offset);
return len == count;
}
// Returns elf_header.e_type if the file pointed by fd is an ELF binary.
static int FileGetElfType(const int fd) {
ElfW(Ehdr) elf_header;
if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
return -1;
}
if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0) {
return -1;
}
return elf_header.e_type;
}
// Read the section headers in the given ELF binary, and if a section
// of the specified type is found, set the output to this section header
// and return true. Otherwise, return false.
// To keep stack consumption low, we would like this function to not get
// inlined.
static ATTRIBUTE_NOINLINE bool
GetSectionHeaderByType(const int fd, ElfW(Half) sh_num, const off_t sh_offset,
ElfW(Word) type, ElfW(Shdr) *out) {
// Read at most 16 section headers at a time to save read calls.
ElfW(Shdr) buf[16];
for (int i = 0; i < sh_num;) {
const ssize_t num_bytes_left = (sh_num - i) * sizeof(buf[0]);
const ssize_t num_bytes_to_read =
(sizeof(buf) > num_bytes_left) ? num_bytes_left : sizeof(buf);
const ssize_t len = ReadFromOffset(fd, buf, num_bytes_to_read,
sh_offset + i * sizeof(buf[0]));
if (len == -1) {
return false;
}
SAFE_ASSERT(len % sizeof(buf[0]) == 0);
const ssize_t num_headers_in_buf = len / sizeof(buf[0]);
SAFE_ASSERT(num_headers_in_buf <= sizeof(buf) / sizeof(buf[0]));
for (int j = 0; j < num_headers_in_buf; ++j) {
if (buf[j].sh_type == type) {
*out = buf[j];
return true;
}
}
i += num_headers_in_buf;
}
return false;
}
// There is no particular reason to limit section name to 63 characters,
// but there has (as yet) been no need for anything longer either.
const int kMaxSectionNameLen = 64;
// name_len should include terminating '\0'.
bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
ElfW(Shdr) *out) {
ElfW(Ehdr) elf_header;
if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
return false;
}
ElfW(Shdr) shstrtab;
off_t shstrtab_offset = (elf_header.e_shoff +
elf_header.e_shentsize * elf_header.e_shstrndx);
if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) {
return false;
}
for (int i = 0; i < elf_header.e_shnum; ++i) {
off_t section_header_offset = (elf_header.e_shoff +
elf_header.e_shentsize * i);
if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) {
return false;
}
char header_name[kMaxSectionNameLen];
if (sizeof(header_name) < name_len) {
RAW_LOG(WARNING, "Section name '%s' is too long (%" PRIuS "); "
"section will not be found (even if present).", name, name_len);
// No point in even trying.
return false;
}
off_t name_offset = shstrtab.sh_offset + out->sh_name;
ssize_t n_read = ReadFromOffset(fd, &header_name, name_len, name_offset);
if (n_read == -1) {
return false;
} else if (n_read != name_len) {
// Short read -- name could be at end of file.
continue;
}
if (memcmp(header_name, name, name_len) == 0) {
return true;
}
}
return false;
}
// Read a symbol table and look for the symbol containing the
// pc. Iterate over symbols in a symbol table and look for the symbol
// containing "pc". On success, return true and write the symbol name
// to out. Otherwise, return false.
// To keep stack consumption low, we would like this function to not get
// inlined.
static ATTRIBUTE_NOINLINE bool
FindSymbol(uint64_t pc, const int fd, char *out, int out_size,
uint64_t symbol_offset, const ElfW(Shdr) *strtab,
const ElfW(Shdr) *symtab) {
if (symtab == NULL) {
return false;
}
const int num_symbols = symtab->sh_size / symtab->sh_entsize;
for (int i = 0; i < num_symbols;) {
off_t offset = symtab->sh_offset + i * symtab->sh_entsize;
// If we are reading Elf64_Sym's, we want to limit this array to
// 32 elements (to keep stack consumption low), otherwise we can
// have a 64 element Elf32_Sym array.
#if __WORDSIZE == 64
#define NUM_SYMBOLS 32
#else
#define NUM_SYMBOLS 64
#endif
// Read at most NUM_SYMBOLS symbols at once to save read() calls.
ElfW(Sym) buf[NUM_SYMBOLS];
int num_symbols_to_read = std::min(NUM_SYMBOLS, num_symbols - i);
const ssize_t len =
ReadFromOffset(fd, &buf, sizeof(buf[0]) * num_symbols_to_read, offset);
SAFE_ASSERT(len % sizeof(buf[0]) == 0);
const ssize_t num_symbols_in_buf = len / sizeof(buf[0]);
SAFE_ASSERT(num_symbols_in_buf <= num_symbols_to_read);
for (int j = 0; j < num_symbols_in_buf; ++j) {
const ElfW(Sym)& symbol = buf[j];
uint64_t start_address = symbol.st_value;
start_address += symbol_offset;
uint64_t end_address = start_address + symbol.st_size;
if (symbol.st_value != 0 && // Skip null value symbols.
symbol.st_shndx != 0 && // Skip undefined symbols.
start_address <= pc && pc < end_address) {
ssize_t len1 = ReadFromOffset(fd, out, out_size,
strtab->sh_offset + symbol.st_name);
if (len1 <= 0 || memchr(out, '\0', out_size) == NULL) {
memset(out, 0, out_size);
return false;
}
return true; // Obtained the symbol name.
}
}
i += num_symbols_in_buf;
}
return false;
}
// Get the symbol name of "pc" from the file pointed by "fd". Process
// both regular and dynamic symbol tables if necessary. On success,
// write the symbol name to "out" and return true. Otherwise, return
// false.
static bool GetSymbolFromObjectFile(const int fd,
uint64_t pc,
char* out,
int out_size,
uint64_t base_address) {
// Read the ELF header.
ElfW(Ehdr) elf_header;
if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
return false;
}
ElfW(Shdr) symtab, strtab;
// Consult a regular symbol table first.
if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
SHT_SYMTAB, &symtab)) {
if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
symtab.sh_link * sizeof(symtab))) {
return false;
}
if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) {
return true; // Found the symbol in a regular symbol table.
}
}
// If the symbol is not found, then consult a dynamic symbol table.
if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
SHT_DYNSYM, &symtab)) {
if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff +
symtab.sh_link * sizeof(symtab))) {
return false;
}
if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) {
return true; // Found the symbol in a dynamic symbol table.
}
}
return false;
}
namespace {
// Thin wrapper around a file descriptor so that the file descriptor
// gets closed for sure.
struct FileDescriptor {
const int fd_;
explicit FileDescriptor(int fd) : fd_(fd) {}
~FileDescriptor() {
if (fd_ >= 0) {
close(fd_);
}
}
int get() { return fd_; }
private:
explicit FileDescriptor(const FileDescriptor&);
void operator=(const FileDescriptor&);
};
// Helper class for reading lines from file.
//
// Note: we don't use ProcMapsIterator since the object is big (it has
// a 5k array member) and uses async-unsafe functions such as sscanf()
// and snprintf().
class LineReader {
public:
explicit LineReader(int fd, char *buf, int buf_len, off_t offset)
: fd_(fd),
buf_(buf),
buf_len_(buf_len),
offset_(offset),
bol_(buf),
eol_(buf),
eod_(buf) {}
// Read '\n'-terminated line from file. On success, modify "bol"
// and "eol", then return true. Otherwise, return false.
//
// Note: if the last line doesn't end with '\n', the line will be
// dropped. It's an intentional behavior to make the code simple.
bool ReadLine(const char **bol, const char **eol) {
if (BufferIsEmpty()) { // First time.
const ssize_t num_bytes = ReadFromOffset(fd_, buf_, buf_len_, offset_);
if (num_bytes <= 0) { // EOF or error.
return false;
}
offset_ += num_bytes;
eod_ = buf_ + num_bytes;
bol_ = buf_;
} else {
bol_ = eol_ + 1; // Advance to the next line in the buffer.
SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_".
if (!HasCompleteLine()) {
const int incomplete_line_length = eod_ - bol_;
// Move the trailing incomplete line to the beginning.
memmove(buf_, bol_, incomplete_line_length);
// Read text from file and append it.
char * const append_pos = buf_ + incomplete_line_length;
const int capacity_left = buf_len_ - incomplete_line_length;
const ssize_t num_bytes =
ReadFromOffset(fd_, append_pos, capacity_left, offset_);
if (num_bytes <= 0) { // EOF or error.
return false;
}
offset_ += num_bytes;
eod_ = append_pos + num_bytes;
bol_ = buf_;
}
}
eol_ = FindLineFeed();
if (eol_ == NULL) { // '\n' not found. Malformed line.
return false;
}
*eol_ = '\0'; // Replace '\n' with '\0'.
*bol = bol_;
*eol = eol_;
return true;
}
// Beginning of line.
const char *bol() {
return bol_;
}
// End of line.
const char *eol() {
return eol_;
}
private:
explicit LineReader(const LineReader&);
void operator=(const LineReader&);
char *FindLineFeed() {
return reinterpret_cast<char *>(memchr(bol_, '\n', eod_ - bol_));
}
bool BufferIsEmpty() {
return buf_ == eod_;
}
bool HasCompleteLine() {
return !BufferIsEmpty() && FindLineFeed() != NULL;
}
const int fd_;
char * const buf_;
const int buf_len_;
off_t offset_;
char *bol_;
char *eol_;
const char *eod_; // End of data in "buf_".
};
} // namespace
// Place the hex number read from "start" into "*hex". The pointer to
// the first non-hex character or "end" is returned.
static char *GetHex(const char *start, const char *end, uint64_t *hex) {
*hex = 0;
const char *p;
for (p = start; p < end; ++p) {
int ch = *p;
if ((ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) {
*hex = (*hex << 4) | (ch < 'A' ? ch - '0' : (ch & 0xF) + 9);
} else { // Encountered the first non-hex character.
break;
}
}
SAFE_ASSERT(p <= end);
return const_cast<char *>(p);
}
// Searches for the object file (from /proc/self/maps) that contains
// the specified pc. If found, sets |start_address| to the start address
// of where this object file is mapped in memory, sets the module base
// address into |base_address|, copies the object file name into
// |out_file_name|, and attempts to open the object file. If the object
// file is opened successfully, returns the file descriptor. Otherwise,
// returns -1. |out_file_name_size| is the size of the file name buffer
// (including the null-terminator).
static ATTRIBUTE_NOINLINE int
OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
uint64_t &start_address,
uint64_t &base_address,
char *out_file_name,
int out_file_name_size) {
int object_fd;
int maps_fd;
NO_INTR(maps_fd = open("/proc/self/maps", O_RDONLY));
FileDescriptor wrapped_maps_fd(maps_fd);
if (wrapped_maps_fd.get() < 0) {
return -1;
}
int mem_fd;
NO_INTR(mem_fd = open("/proc/self/mem", O_RDONLY));
FileDescriptor wrapped_mem_fd(mem_fd);
if (wrapped_mem_fd.get() < 0) {
return -1;
}
// Iterate over maps and look for the map containing the pc. Then
// look into the symbol tables inside.
char buf[1024]; // Big enough for line of sane /proc/self/maps
int num_maps = 0;
LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf), 0);
while (true) {
num_maps++;
const char *cursor;
const char *eol;
if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line.
return -1;
}
// Start parsing line in /proc/self/maps. Here is an example:
//
// 08048000-0804c000 r-xp 00000000 08:01 2142121 /bin/cat
//
// We want start address (08048000), end address (0804c000), flags
// (r-xp) and file name (/bin/cat).
// Read start address.
cursor = GetHex(cursor, eol, &start_address);
if (cursor == eol || *cursor != '-') {
return -1; // Malformed line.
}
++cursor; // Skip '-'.
// Read end address.
uint64_t end_address;
cursor = GetHex(cursor, eol, &end_address);
if (cursor == eol || *cursor != ' ') {
return -1; // Malformed line.
}
++cursor; // Skip ' '.
// Read flags. Skip flags until we encounter a space or eol.
const char * const flags_start = cursor;
while (cursor < eol && *cursor != ' ') {
++cursor;
}
// We expect at least four letters for flags (ex. "r-xp").
if (cursor == eol || cursor < flags_start + 4) {
return -1; // Malformed line.
}
// Determine the base address by reading ELF headers in process memory.
ElfW(Ehdr) ehdr;
// Skip non-readable maps.
if (flags_start[0] == 'r' &&
ReadFromOffsetExact(mem_fd, &ehdr, sizeof(ElfW(Ehdr)), start_address) &&
memcmp(ehdr.e_ident, ELFMAG, SELFMAG) == 0) {
switch (ehdr.e_type) {
case ET_EXEC:
base_address = 0;
break;
case ET_DYN:
// Find the segment containing file offset 0. This will correspond
// to the ELF header that we just read. Normally this will have
// virtual address 0, but this is not guaranteed. We must subtract
// the virtual address from the address where the ELF header was
// mapped to get the base address.
//
// If we fail to find a segment for file offset 0, use the address
// of the ELF header as the base address.
base_address = start_address;
for (unsigned i = 0; i != ehdr.e_phnum; ++i) {
ElfW(Phdr) phdr;
if (ReadFromOffsetExact(
mem_fd, &phdr, sizeof(phdr),
start_address + ehdr.e_phoff + i * sizeof(phdr)) &&
phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
base_address = start_address - phdr.p_vaddr;
break;
}
}
break;
default:
// ET_REL or ET_CORE. These aren't directly executable, so they don't
// affect the base address.
break;
}
}
// Check start and end addresses.
if (!(start_address <= pc && pc < end_address)) {
continue; // We skip this map. PC isn't in this map.
}
// Check flags. We are only interested in "r*x" maps.
if (flags_start[0] != 'r' || flags_start[2] != 'x') {
continue; // We skip this map.
}
++cursor; // Skip ' '.
// Read file offset.
uint64_t file_offset;
cursor = GetHex(cursor, eol, &file_offset);
if (cursor == eol || *cursor != ' ') {
return -1; // Malformed line.
}
++cursor; // Skip ' '.
// Skip to file name. "cursor" now points to dev. We need to
// skip at least two spaces for dev and inode.
int num_spaces = 0;
while (cursor < eol) {
if (*cursor == ' ') {
++num_spaces;
} else if (num_spaces >= 2) {
// The first non-space character after skipping two spaces
// is the beginning of the file name.
break;
}
++cursor;
}
if (cursor == eol) {
return -1; // Malformed line.
}
// Finally, "cursor" now points to file name of our interest.
NO_INTR(object_fd = open(cursor, O_RDONLY));
if (object_fd < 0) {
// Failed to open object file. Copy the object file name to
// |out_file_name|.
strncpy(out_file_name, cursor, out_file_name_size);
// Making sure |out_file_name| is always null-terminated.
out_file_name[out_file_name_size - 1] = '\0';
return -1;
}
return object_fd;
}
}
// POSIX doesn't define any async-signal safe function for converting
// an integer to ASCII. We'll have to define our own version.
// itoa_r() converts a (signed) integer to ASCII. It returns "buf", if the
// conversion was successful or NULL otherwise. It never writes more than "sz"
// bytes. Output will be truncated as needed, and a NUL character is always
// appended.
// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
static char *itoa_r(intptr_t i, char *buf, size_t sz, int base, size_t padding) {
// Make sure we can write at least one NUL byte.
size_t n = 1;
if (n > sz)
return NULL;
if (base < 2 || base > 16) {
buf[0] = '\000';
return NULL;
}
char *start = buf;
uintptr_t j = i;
// Handle negative numbers (only for base 10).
if (i < 0 && base == 10) {
// This does "j = -i" while avoiding integer overflow.
j = static_cast<uintptr_t>(-(i + 1)) + 1;
// Make sure we can write the '-' character.
if (++n > sz) {
buf[0] = '\000';
return NULL;
}
*start++ = '-';
}
// Loop until we have converted the entire number. Output at least one
// character (i.e. '0').
char *ptr = start;
do {
// Make sure there is still enough space left in our output buffer.
if (++n > sz) {
buf[0] = '\000';
return NULL;
}
// Output the next digit.
*ptr++ = "0123456789abcdef"[j % base];
j /= base;
if (padding > 0)
padding--;
} while (j > 0 || padding > 0);
// Terminate the output with a NUL character.
*ptr = '\000';
// Conversion to ASCII actually resulted in the digits being in reverse
// order. We can't easily generate them in forward order, as we can't tell
// the number of characters needed until we are done converting.
// So, now, we reverse the string (except for the possible "-" sign).
while (--ptr > start) {
char ch = *ptr;
*ptr = *start;
*start++ = ch;
}
return buf;
}
// Safely appends string |source| to string |dest|. Never writes past the
// buffer size |dest_size| and guarantees that |dest| is null-terminated.
static void SafeAppendString(const char* source, char* dest, int dest_size) {
int dest_string_length = strlen(dest);
SAFE_ASSERT(dest_string_length < dest_size);
dest += dest_string_length;
dest_size -= dest_string_length;
strncpy(dest, source, dest_size);
// Making sure |dest| is always null-terminated.
dest[dest_size - 1] = '\0';
}
// Converts a 64-bit value into a hex string, and safely appends it to |dest|.
// Never writes past the buffer size |dest_size| and guarantees that |dest| is
// null-terminated.
static void SafeAppendHexNumber(uint64_t value, char* dest, int dest_size) {
// 64-bit numbers in hex can have up to 16 digits.
char buf[17] = {'\0'};
SafeAppendString(itoa_r(value, buf, sizeof(buf), 16, 0), dest, dest_size);
}
// The implementation of our symbolization routine. If it
// successfully finds the symbol containing "pc" and obtains the
// symbol name, returns true and write the symbol name to "out".
// Otherwise, returns false. If Callback function is installed via
// InstallSymbolizeCallback(), the function is also called in this function,
// and "out" is used as its output.
// To keep stack consumption low, we would like this function to not
// get inlined.
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
int out_size) {
uint64_t pc0 = reinterpret_cast<uintptr_t>(pc);
uint64_t start_address = 0;
uint64_t base_address = 0;
int object_fd = -1;
if (out_size < 1) {
return false;
}
out[0] = '\0';
SafeAppendString("(", out, out_size);
if (g_symbolize_open_object_file_callback) {
object_fd = g_symbolize_open_object_file_callback(pc0, start_address,
base_address, out + 1,
out_size - 1);
} else {
object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0, start_address,
base_address,
out + 1,
out_size - 1);
}
FileDescriptor wrapped_object_fd(object_fd);
#if defined(PRINT_UNSYMBOLIZED_STACK_TRACES)
{
#else
// Check whether a file name was returned.
if (object_fd < 0) {
#endif
if (out[1]) {
// The object file containing PC was determined successfully however the
// object file was not opened successfully. This is still considered
// success because the object file name and offset are known and tools
// like asan_symbolize.py can be used for the symbolization.
out[out_size - 1] = '\0'; // Making sure |out| is always null-terminated.
SafeAppendString("+0x", out, out_size);
SafeAppendHexNumber(pc0 - base_address, out, out_size);
SafeAppendString(")", out, out_size);
return true;
}
// Failed to determine the object file containing PC. Bail out.
return false;
}
int elf_type = FileGetElfType(wrapped_object_fd.get());
if (elf_type == -1) {
return false;
}
if (g_symbolize_callback) {
// Run the call back if it's installed.
// Note: relocation (and much of the rest of this code) will be
// wrong for prelinked shared libraries and PIE executables.
uint64_t relocation = (elf_type == ET_DYN) ? start_address : 0;
int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(),
pc, out, out_size,
relocation);
if (num_bytes_written > 0) {
out += num_bytes_written;
out_size -= num_bytes_written;
}
}
if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0,
out, out_size, base_address)) {
if (out[1] && !g_symbolize_callback) {
// The object file containing PC was opened successfully however the
// symbol was not found. The object may have been stripped. This is still
// considered success because the object file name and offset are known
// and tools like asan_symbolize.py can be used for the symbolization.
out[out_size - 1] = '\0'; // Making sure |out| is always null-terminated.
SafeAppendString("+0x", out, out_size);
SafeAppendHexNumber(pc0 - base_address, out, out_size);
SafeAppendString(")", out, out_size);
return true;
}
return false;
}
// Symbolization succeeded. Now we try to demangle the symbol.
DemangleInplace(out, out_size);
return true;
}
_END_GOOGLE_NAMESPACE_
#elif defined(OS_MACOSX) && defined(HAVE_DLADDR)
#include <dlfcn.h>
#include <string.h>
_START_GOOGLE_NAMESPACE_
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
int out_size) {
Dl_info info;
if (dladdr(pc, &info)) {
if ((int)strlen(info.dli_sname) < out_size) {
strcpy(out, info.dli_sname);
// Symbolization succeeded. Now we try to demangle the symbol.
DemangleInplace(out, out_size);
return true;
}
}
return false;
}
_END_GOOGLE_NAMESPACE_
#elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
#include <windows.h>
#include <dbghelp.h>
#ifdef _MSC_VER
#pragma comment(lib, "dbghelp")
#endif
_START_GOOGLE_NAMESPACE_
class SymInitializer {
public:
HANDLE process;
bool ready;
SymInitializer() : process(NULL), ready(false) {
// Initialize the symbol handler.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680344(v=vs.85).aspx
process = GetCurrentProcess();
// Defer symbol loading.
// We do not request undecorated symbols with SYMOPT_UNDNAME
// because the mangling library calls UnDecorateSymbolName.
SymSetOptions(SYMOPT_DEFERRED_LOADS);
if (SymInitialize(process, NULL, true)) {
ready = true;
}
}
~SymInitializer() {
SymCleanup(process);
// We do not need to close `HANDLE process` because it's a "pseudo handle."
}
private:
SymInitializer(const SymInitializer&);
SymInitializer& operator=(const SymInitializer&);
};
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
int out_size) {
const static SymInitializer symInitializer;
if (!symInitializer.ready) {
return false;
}
// Resolve symbol information from address.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx
char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
SYMBOL_INFO *symbol = reinterpret_cast<SYMBOL_INFO *>(buf);
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME;
// We use the ANSI version to ensure the string type is always `char *`.
// This could break if a symbol has Unicode in it.
BOOL ret = SymFromAddr(symInitializer.process,
reinterpret_cast<DWORD64>(pc), 0, symbol);
if (ret == 1 && static_cast<int>(symbol->NameLen) < out_size) {
// `NameLen` does not include the null terminating character.
strncpy(out, symbol->Name, static_cast<size_t>(symbol->NameLen) + 1);
out[static_cast<size_t>(symbol->NameLen)] = '\0';
// Symbolization succeeded. Now we try to demangle the symbol.
DemangleInplace(out, out_size);
return true;
}
return false;
}
_END_GOOGLE_NAMESPACE_
#else
# error BUG: HAVE_SYMBOLIZE was wrongly set
#endif
_START_GOOGLE_NAMESPACE_
bool Symbolize(void *pc, char *out, int out_size) {
SAFE_ASSERT(out_size >= 0);
return SymbolizeAndDemangle(pc, out, out_size);
}
_END_GOOGLE_NAMESPACE_
#else /* HAVE_SYMBOLIZE */
#include <assert.h>
#include "config.h"
_START_GOOGLE_NAMESPACE_
// TODO: Support other environments.
bool Symbolize(void *pc, char *out, int out_size) {
assert(0);
return false;
}
_END_GOOGLE_NAMESPACE_
#endif

158
third_party/glog/src/symbolize.h vendored Normal file
View file

@ -0,0 +1,158 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// This library provides Symbolize() function that symbolizes program
// counters to their corresponding symbol names on linux platforms.
// This library has a minimal implementation of an ELF symbol table
// reader (i.e. it doesn't depend on libelf, etc.).
//
// The algorithm used in Symbolize() is as follows.
//
// 1. Go through a list of maps in /proc/self/maps and find the map
// containing the program counter.
//
// 2. Open the mapped file and find a regular symbol table inside.
// Iterate over symbols in the symbol table and look for the symbol
// containing the program counter. If such a symbol is found,
// obtain the symbol name, and demangle the symbol if possible.
// If the symbol isn't found in the regular symbol table (binary is
// stripped), try the same thing with a dynamic symbol table.
//
// Note that Symbolize() is originally implemented to be used in
// FailureSignalHandler() in base/google.cc. Hence it doesn't use
// malloc() and other unsafe operations. It should be both
// thread-safe and async-signal-safe.
#ifndef BASE_SYMBOLIZE_H_
#define BASE_SYMBOLIZE_H_
#include "utilities.h"
#include "config.h"
#include "glog/logging.h"
#ifdef HAVE_SYMBOLIZE
#if defined(__ELF__) // defined by gcc
#if defined(__OpenBSD__)
#include <sys/exec_elf.h>
#else
#include <elf.h>
#endif
#if !defined(ANDROID)
#include <link.h> // For ElfW() macro.
#endif
// For systems where SIZEOF_VOID_P is not defined, determine it
// based on __LP64__ (defined by gcc on 64-bit systems)
#if !defined(SIZEOF_VOID_P)
# if defined(__LP64__)
# define SIZEOF_VOID_P 8
# else
# define SIZEOF_VOID_P 4
# endif
#endif
// If there is no ElfW macro, let's define it by ourself.
#ifndef ElfW
# if SIZEOF_VOID_P == 4
# define ElfW(type) Elf32_##type
# elif SIZEOF_VOID_P == 8
# define ElfW(type) Elf64_##type
# else
# error "Unknown sizeof(void *)"
# endif
#endif
_START_GOOGLE_NAMESPACE_
// Gets the section header for the given name, if it exists. Returns true on
// success. Otherwise, returns false.
bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
ElfW(Shdr) *out);
_END_GOOGLE_NAMESPACE_
#endif /* __ELF__ */
_START_GOOGLE_NAMESPACE_
// Restrictions on the callbacks that follow:
// - The callbacks must not use heaps but only use stacks.
// - The callbacks must be async-signal-safe.
// Installs a callback function, which will be called right before a symbol name
// is printed. The callback is intended to be used for showing a file name and a
// line number preceding a symbol name.
// "fd" is a file descriptor of the object file containing the program
// counter "pc". The callback function should write output to "out"
// and return the size of the output written. On error, the callback
// function should return -1.
typedef int (*SymbolizeCallback)(int fd,
void* pc,
char* out,
size_t out_size,
uint64_t relocation);
void InstallSymbolizeCallback(SymbolizeCallback callback);
// Installs a callback function, which will be called instead of
// OpenObjectFileContainingPcAndGetStartAddress. The callback is expected
// to searches for the object file (from /proc/self/maps) that contains
// the specified pc. If found, sets |start_address| to the start address
// of where this object file is mapped in memory, sets the module base
// address into |base_address|, copies the object file name into
// |out_file_name|, and attempts to open the object file. If the object
// file is opened successfully, returns the file descriptor. Otherwise,
// returns -1. |out_file_name_size| is the size of the file name buffer
// (including the null-terminator).
typedef int (*SymbolizeOpenObjectFileCallback)(uint64_t pc,
uint64_t& start_address,
uint64_t& base_address,
char* out_file_name,
int out_file_name_size);
void InstallSymbolizeOpenObjectFileCallback(
SymbolizeOpenObjectFileCallback callback);
_END_GOOGLE_NAMESPACE_
#endif
_START_GOOGLE_NAMESPACE_
// Symbolizes a program counter. On success, returns true and write the
// symbol name to "out". The symbol name is demangled if possible
// (supports symbols generated by GCC 3.x or newer). Otherwise,
// returns false.
GOOGLE_GLOG_DLL_DECL bool Symbolize(void *pc, char *out, int out_size);
_END_GOOGLE_NAMESPACE_
#endif // BASE_SYMBOLIZE_H_

View file

@ -0,0 +1,425 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// Unit tests for functions in symbolize.cc.
#include "utilities.h"
#include <signal.h>
#include <iostream>
#include "glog/logging.h"
#include "symbolize.h"
#include "googletest.h"
#include "config.h"
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE;
#endif
using namespace std;
using namespace GOOGLE_NAMESPACE;
#if defined(HAVE_STACKTRACE)
#define always_inline
// A wrapper function for Symbolize() to make the unit test simple.
static const char *TrySymbolize(void *pc) {
static char symbol[4096];
if (Symbolize(pc, symbol, sizeof(symbol))) {
return symbol;
} else {
return NULL;
}
}
# if defined(__ELF__)
// This unit tests make sense only with GCC.
// Uses lots of GCC specific features.
#if defined(__GNUC__) && !defined(__OPENCC__)
# if __GNUC__ >= 4
# define TEST_WITH_MODERN_GCC
# if __i386__ // always_inline isn't supported for x86_64 with GCC 4.1.0.
# undef always_inline
# define always_inline __attribute__((always_inline))
# define HAVE_ALWAYS_INLINE
# endif // __i386__
# else
# endif // __GNUC__ >= 4
# if defined(__i386__) || defined(__x86_64__)
# define TEST_X86_32_AND_64 1
# endif // defined(__i386__) || defined(__x86_64__)
#endif
// Make them C linkage to avoid mangled names.
extern "C" {
void nonstatic_func();
void nonstatic_func() {
volatile int a = 0;
++a;
}
static void static_func() {
volatile int a = 0;
++a;
}
}
TEST(Symbolize, Symbolize) {
// We do C-style cast since GCC 2.95.3 doesn't allow
// reinterpret_cast<void *>(&func).
// Compilers should give us pointers to them.
EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func)));
// The name of an internal linkage symbol is not specified; allow either a
// mangled or an unmangled name here.
const char *static_func_symbol = TrySymbolize((void *)(&static_func));
CHECK(NULL != static_func_symbol);
EXPECT_TRUE(strcmp("static_func", static_func_symbol) == 0 ||
strcmp("static_func()", static_func_symbol) == 0);
EXPECT_TRUE(NULL == TrySymbolize(NULL));
}
struct Foo {
static void func(int x);
};
void ATTRIBUTE_NOINLINE Foo::func(int x) {
volatile int a = x;
++a;
}
// With a modern GCC, Symbolize() should return demangled symbol
// names. Function parameters should be omitted.
#ifdef TEST_WITH_MODERN_GCC
TEST(Symbolize, SymbolizeWithDemangling) {
Foo::func(100);
EXPECT_STREQ("Foo::func()", TrySymbolize((void *)(&Foo::func)));
}
#endif
// Tests that verify that Symbolize footprint is within some limit.
// To measure the stack footprint of the Symbolize function, we create
// a signal handler (for SIGUSR1 say) that calls the Symbolize function
// on an alternate stack. This alternate stack is initialized to some
// known pattern (0x55, 0x55, 0x55, ...). We then self-send this signal,
// and after the signal handler returns, look at the alternate stack
// buffer to see what portion has been touched.
//
// This trick gives us the the stack footprint of the signal handler.
// But the signal handler, even before the call to Symbolize, consumes
// some stack already. We however only want the stack usage of the
// Symbolize function. To measure this accurately, we install two signal
// handlers: one that does nothing and just returns, and another that
// calls Symbolize. The difference between the stack consumption of these
// two signals handlers should give us the Symbolize stack foorprint.
static void *g_pc_to_symbolize;
static char g_symbolize_buffer[4096];
static char *g_symbolize_result;
static void EmptySignalHandler(int signo) {}
static void SymbolizeSignalHandler(int signo) {
if (Symbolize(g_pc_to_symbolize, g_symbolize_buffer,
sizeof(g_symbolize_buffer))) {
g_symbolize_result = g_symbolize_buffer;
} else {
g_symbolize_result = NULL;
}
}
const int kAlternateStackSize = 8096;
const char kAlternateStackFillValue = 0x55;
// These helper functions look at the alternate stack buffer, and figure
// out what portion of this buffer has been touched - this is the stack
// consumption of the signal handler running on this alternate stack.
static ATTRIBUTE_NOINLINE bool StackGrowsDown(int *x) {
int y;
return &y < x;
}
static int GetStackConsumption(const char* alt_stack) {
int x;
if (StackGrowsDown(&x)) {
for (int i = 0; i < kAlternateStackSize; i++) {
if (alt_stack[i] != kAlternateStackFillValue) {
return (kAlternateStackSize - i);
}
}
} else {
for (int i = (kAlternateStackSize - 1); i >= 0; i--) {
if (alt_stack[i] != kAlternateStackFillValue) {
return i;
}
}
}
return -1;
}
#ifdef HAVE_SIGALTSTACK
// Call Symbolize and figure out the stack footprint of this call.
static const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) {
g_pc_to_symbolize = pc;
// The alt-signal-stack cannot be heap allocated because there is a
// bug in glibc-2.2 where some signal handler setup code looks at the
// current stack pointer to figure out what thread is currently running.
// Therefore, the alternate stack must be allocated from the main stack
// itself.
char altstack[kAlternateStackSize];
memset(altstack, kAlternateStackFillValue, kAlternateStackSize);
// Set up the alt-signal-stack (and save the older one).
stack_t sigstk;
memset(&sigstk, 0, sizeof(stack_t));
stack_t old_sigstk;
sigstk.ss_sp = altstack;
sigstk.ss_size = kAlternateStackSize;
sigstk.ss_flags = 0;
CHECK_ERR(sigaltstack(&sigstk, &old_sigstk));
// Set up SIGUSR1 and SIGUSR2 signal handlers (and save the older ones).
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
struct sigaction old_sa1, old_sa2;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_ONSTACK;
// SIGUSR1 maps to EmptySignalHandler.
sa.sa_handler = EmptySignalHandler;
CHECK_ERR(sigaction(SIGUSR1, &sa, &old_sa1));
// SIGUSR2 maps to SymbolizeSignalHanlder.
sa.sa_handler = SymbolizeSignalHandler;
CHECK_ERR(sigaction(SIGUSR2, &sa, &old_sa2));
// Send SIGUSR1 signal and measure the stack consumption of the empty
// signal handler.
CHECK_ERR(kill(getpid(), SIGUSR1));
int stack_consumption1 = GetStackConsumption(altstack);
// Send SIGUSR2 signal and measure the stack consumption of the symbolize
// signal handler.
CHECK_ERR(kill(getpid(), SIGUSR2));
int stack_consumption2 = GetStackConsumption(altstack);
// The difference between the two stack consumption values is the
// stack footprint of the Symbolize function.
if (stack_consumption1 != -1 && stack_consumption2 != -1) {
*stack_consumed = stack_consumption2 - stack_consumption1;
} else {
*stack_consumed = -1;
}
// Log the stack consumption values.
LOG(INFO) << "Stack consumption of empty signal handler: "
<< stack_consumption1;
LOG(INFO) << "Stack consumption of symbolize signal handler: "
<< stack_consumption2;
LOG(INFO) << "Stack consumption of Symbolize: " << *stack_consumed;
// Now restore the old alt-signal-stack and signal handlers.
CHECK_ERR(sigaltstack(&old_sigstk, NULL));
CHECK_ERR(sigaction(SIGUSR1, &old_sa1, NULL));
CHECK_ERR(sigaction(SIGUSR2, &old_sa2, NULL));
return g_symbolize_result;
}
#ifdef __ppc64__
// Symbolize stack consumption should be within 4kB.
const int kStackConsumptionUpperLimit = 4096;
#else
// Symbolize stack consumption should be within 2kB.
const int kStackConsumptionUpperLimit = 2048;
#endif
TEST(Symbolize, SymbolizeStackConsumption) {
int stack_consumed;
const char* symbol;
symbol = SymbolizeStackConsumption((void *)(&nonstatic_func),
&stack_consumed);
EXPECT_STREQ("nonstatic_func", symbol);
EXPECT_GT(stack_consumed, 0);
EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
// The name of an internal linkage symbol is not specified; allow either a
// mangled or an unmangled name here.
symbol = SymbolizeStackConsumption((void *)(&static_func),
&stack_consumed);
CHECK(NULL != symbol);
EXPECT_TRUE(strcmp("static_func", symbol) == 0 ||
strcmp("static_func()", symbol) == 0);
EXPECT_GT(stack_consumed, 0);
EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
}
#ifdef TEST_WITH_MODERN_GCC
TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) {
Foo::func(100);
int stack_consumed;
const char* symbol;
symbol = SymbolizeStackConsumption((void *)(&Foo::func), &stack_consumed);
EXPECT_STREQ("Foo::func()", symbol);
EXPECT_GT(stack_consumed, 0);
EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
}
#endif
#endif // HAVE_SIGALTSTACK
// x86 specific tests. Uses some inline assembler.
extern "C" {
inline void* always_inline inline_func() {
void *pc = NULL;
#ifdef TEST_X86_32_AND_64
__asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
#endif
return pc;
}
void* ATTRIBUTE_NOINLINE non_inline_func();
void* ATTRIBUTE_NOINLINE non_inline_func() {
void *pc = NULL;
#ifdef TEST_X86_32_AND_64
__asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
#endif
return pc;
}
static void ATTRIBUTE_NOINLINE TestWithPCInsideNonInlineFunction() {
#if defined(TEST_X86_32_AND_64) && defined(HAVE_ATTRIBUTE_NOINLINE)
void *pc = non_inline_func();
const char *symbol = TrySymbolize(pc);
CHECK(symbol != NULL);
CHECK_STREQ(symbol, "non_inline_func");
cout << "Test case TestWithPCInsideNonInlineFunction passed." << endl;
#endif
}
static void ATTRIBUTE_NOINLINE TestWithPCInsideInlineFunction() {
#if defined(TEST_X86_32_AND_64) && defined(HAVE_ALWAYS_INLINE)
void *pc = inline_func(); // Must be inlined.
const char *symbol = TrySymbolize(pc);
CHECK(symbol != NULL);
CHECK_STREQ(symbol, __FUNCTION__);
cout << "Test case TestWithPCInsideInlineFunction passed." << endl;
#endif
}
}
// Test with a return address.
static void ATTRIBUTE_NOINLINE TestWithReturnAddress() {
#if defined(HAVE_ATTRIBUTE_NOINLINE)
void *return_address = __builtin_return_address(0);
const char *symbol = TrySymbolize(return_address);
CHECK(symbol != NULL);
CHECK_STREQ(symbol, "main");
cout << "Test case TestWithReturnAddress passed." << endl;
#endif
}
# elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
#ifdef _MSC_VER
#include <intrin.h>
#pragma intrinsic(_ReturnAddress)
#endif
struct Foo {
static void func(int x);
};
__declspec(noinline) void Foo::func(int x) {
volatile int a = x;
++a;
}
TEST(Symbolize, SymbolizeWithDemangling) {
Foo::func(100);
const char* ret = TrySymbolize((void *)(&Foo::func));
EXPECT_STREQ("public: static void __cdecl Foo::func(int)", ret);
}
__declspec(noinline) void TestWithReturnAddress() {
void *return_address =
#ifdef __GNUC__ // Cygwin and MinGW support
__builtin_return_address(0)
#else
_ReturnAddress()
#endif
;
const char *symbol = TrySymbolize(return_address);
CHECK(symbol != NULL);
CHECK_STREQ(symbol, "main");
cout << "Test case TestWithReturnAddress passed." << endl;
}
# endif // __ELF__
#endif // HAVE_STACKTRACE
int main(int argc, char **argv) {
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
InitGoogleTest(&argc, argv);
#if defined(HAVE_SYMBOLIZE) && defined(HAVE_STACKTRACE)
# if defined(__ELF__)
// We don't want to get affected by the callback interface, that may be
// used to install some callback function at InitGoogle() time.
InstallSymbolizeCallback(NULL);
TestWithPCInsideInlineFunction();
TestWithPCInsideNonInlineFunction();
TestWithReturnAddress();
return RUN_ALL_TESTS();
# elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
TestWithReturnAddress();
return RUN_ALL_TESTS();
# else // OS_WINDOWS
printf("PASS (no symbolize_unittest support)\n");
return 0;
# endif // __ELF__
#else
printf("PASS (no symbolize support)\n");
return 0;
#endif // HAVE_SYMBOLIZE
}

374
third_party/glog/src/utilities.cc vendored Normal file
View file

@ -0,0 +1,374 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Shinichiro Hamaji
#include "utilities.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <time.h>
#if defined(HAVE_SYSCALL_H)
#include <syscall.h> // for syscall()
#elif defined(HAVE_SYS_SYSCALL_H)
#include <sys/syscall.h> // for syscall()
#endif
#ifdef HAVE_SYSLOG_H
# include <syslog.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h> // For geteuid.
#endif
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#include "base/googleinit.h"
using std::string;
_START_GOOGLE_NAMESPACE_
static const char* g_program_invocation_short_name = NULL;
_END_GOOGLE_NAMESPACE_
// The following APIs are all internal.
#ifdef HAVE_STACKTRACE
#include "stacktrace.h"
#include "symbolize.h"
#include "base/commandlineflags.h"
GLOG_DEFINE_bool(symbolize_stacktrace, true,
"Symbolize the stack trace in the tombstone");
_START_GOOGLE_NAMESPACE_
typedef void DebugWriter(const char*, void*);
// The %p field width for printf() functions is two characters per byte.
// For some environments, add two extra bytes for the leading "0x".
static const int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);
static void DebugWriteToStderr(const char* data, void *) {
// This one is signal-safe.
if (write(STDERR_FILENO, data, strlen(data)) < 0) {
// Ignore errors.
}
}
static void DebugWriteToString(const char* data, void *arg) {
reinterpret_cast<string*>(arg)->append(data);
}
#ifdef HAVE_SYMBOLIZE
// Print a program counter and its symbol name.
static void DumpPCAndSymbol(DebugWriter *writerfn, void *arg, void *pc,
const char * const prefix) {
char tmp[1024];
const char *symbol = "(unknown)";
// Symbolizes the previous address of pc because pc may be in the
// next function. The overrun happens when the function ends with
// a call to a function annotated noreturn (e.g. CHECK).
if (Symbolize(reinterpret_cast<char *>(pc) - 1, tmp, sizeof(tmp))) {
symbol = tmp;
}
char buf[1024];
snprintf(buf, sizeof(buf), "%s@ %*p %s\n",
prefix, kPrintfPointerFieldWidth, pc, symbol);
writerfn(buf, arg);
}
#endif
static void DumpPC(DebugWriter *writerfn, void *arg, void *pc,
const char * const prefix) {
char buf[100];
snprintf(buf, sizeof(buf), "%s@ %*p\n",
prefix, kPrintfPointerFieldWidth, pc);
writerfn(buf, arg);
}
// Dump current stack trace as directed by writerfn
static void DumpStackTrace(int skip_count, DebugWriter *writerfn, void *arg) {
// Print stack trace
void* stack[32];
int depth = GetStackTrace(stack, ARRAYSIZE(stack), skip_count+1);
for (int i = 0; i < depth; i++) {
#if defined(HAVE_SYMBOLIZE)
if (FLAGS_symbolize_stacktrace) {
DumpPCAndSymbol(writerfn, arg, stack[i], " ");
} else {
DumpPC(writerfn, arg, stack[i], " ");
}
#else
DumpPC(writerfn, arg, stack[i], " ");
#endif
}
}
static void DumpStackTraceAndExit() {
DumpStackTrace(1, DebugWriteToStderr, NULL);
// TODO(hamaji): Use signal instead of sigaction?
if (IsFailureSignalHandlerInstalled()) {
// Set the default signal handler for SIGABRT, to avoid invoking our
// own signal handler installed by InstallFailureSignalHandler().
#ifdef HAVE_SIGACTION
struct sigaction sig_action;
memset(&sig_action, 0, sizeof(sig_action));
sigemptyset(&sig_action.sa_mask);
sig_action.sa_handler = SIG_DFL;
sigaction(SIGABRT, &sig_action, NULL);
#elif defined(OS_WINDOWS)
signal(SIGABRT, SIG_DFL);
#endif // HAVE_SIGACTION
}
abort();
}
_END_GOOGLE_NAMESPACE_
#endif // HAVE_STACKTRACE
_START_GOOGLE_NAMESPACE_
namespace glog_internal_namespace_ {
const char* ProgramInvocationShortName() {
if (g_program_invocation_short_name != NULL) {
return g_program_invocation_short_name;
} else {
// TODO(hamaji): Use /proc/self/cmdline and so?
return "UNKNOWN";
}
}
bool IsGoogleLoggingInitialized() {
return g_program_invocation_short_name != NULL;
}
#ifdef OS_WINDOWS
struct timeval {
long tv_sec, tv_usec;
};
// Based on: http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd
// See COPYING for copyright information.
static int gettimeofday(struct timeval *tv, void* tz) {
#define EPOCHFILETIME (116444736000000000ULL)
FILETIME ft;
LARGE_INTEGER li;
uint64 tt;
GetSystemTimeAsFileTime(&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
tt = (li.QuadPart - EPOCHFILETIME) / 10;
tv->tv_sec = tt / 1000000;
tv->tv_usec = tt % 1000000;
return 0;
}
#endif
int64 CycleClock_Now() {
// TODO(hamaji): temporary impementation - it might be too slow.
struct timeval tv;
gettimeofday(&tv, NULL);
return static_cast<int64>(tv.tv_sec) * 1000000 + tv.tv_usec;
}
int64 UsecToCycles(int64 usec) {
return usec;
}
WallTime WallTime_Now() {
// Now, cycle clock is retuning microseconds since the epoch.
return CycleClock_Now() * 0.000001;
}
static int32 g_main_thread_pid = getpid();
int32 GetMainThreadPid() {
return g_main_thread_pid;
}
bool PidHasChanged() {
int32 pid = getpid();
if (g_main_thread_pid == pid) {
return false;
}
g_main_thread_pid = pid;
return true;
}
pid_t GetTID() {
// On Linux and MacOSX, we try to use gettid().
#if defined OS_LINUX || defined OS_MACOSX
#ifndef __NR_gettid
#ifdef OS_MACOSX
#define __NR_gettid SYS_gettid
#elif ! defined __i386__
#error "Must define __NR_gettid for non-x86 platforms"
#else
#define __NR_gettid 224
#endif
#endif
static bool lacks_gettid = false;
if (!lacks_gettid) {
pid_t tid = syscall(__NR_gettid);
if (tid != -1) {
return tid;
}
// Technically, this variable has to be volatile, but there is a small
// performance penalty in accessing volatile variables and there should
// not be any serious adverse effect if a thread does not immediately see
// the value change to "true".
lacks_gettid = true;
}
#endif // OS_LINUX || OS_MACOSX
// If gettid() could not be used, we use one of the following.
#if defined OS_LINUX
return getpid(); // Linux: getpid returns thread ID when gettid is absent
#elif defined OS_WINDOWS && !defined OS_CYGWIN
return GetCurrentThreadId();
#elif defined(HAVE_PTHREAD)
// If none of the techniques above worked, we use pthread_self().
return (pid_t)(uintptr_t)pthread_self();
#else
return -1;
#endif
}
const char* const_basename(const char* filepath) {
const char* base = strrchr(filepath, '/');
#ifdef OS_WINDOWS // Look for either path separator in Windows
if (!base)
base = strrchr(filepath, '\\');
#endif
return base ? (base+1) : filepath;
}
static string g_my_user_name;
const string& MyUserName() {
return g_my_user_name;
}
static void MyUserNameInitializer() {
// TODO(hamaji): Probably this is not portable.
#if defined(OS_WINDOWS)
const char* user = getenv("USERNAME");
#else
const char* user = getenv("USER");
#endif
if (user != NULL) {
g_my_user_name = user;
} else {
#if defined(HAVE_PWD_H) && defined(HAVE_UNISTD_H)
struct passwd pwd;
struct passwd* result = NULL;
char buffer[1024] = {'\0'};
uid_t uid = geteuid();
int pwuid_res = getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &result);
if (pwuid_res == 0 && result) {
g_my_user_name = pwd.pw_name;
} else {
snprintf(buffer, sizeof(buffer), "uid%d", uid);
g_my_user_name = buffer;
}
#endif
if (g_my_user_name.empty()) {
g_my_user_name = "invalid-user";
}
}
}
REGISTER_MODULE_INITIALIZER(utilities, MyUserNameInitializer());
#ifdef HAVE_STACKTRACE
void DumpStackTraceToString(string* stacktrace) {
DumpStackTrace(1, DebugWriteToString, stacktrace);
}
#endif
// We use an atomic operation to prevent problems with calling CrashReason
// from inside the Mutex implementation (potentially through RAW_CHECK).
static const CrashReason* g_reason = 0;
void SetCrashReason(const CrashReason* r) {
sync_val_compare_and_swap(&g_reason,
reinterpret_cast<const CrashReason*>(0),
r);
}
void InitGoogleLoggingUtilities(const char* argv0) {
CHECK(!IsGoogleLoggingInitialized())
<< "You called InitGoogleLogging() twice!";
const char* slash = strrchr(argv0, '/');
#ifdef OS_WINDOWS
if (!slash) slash = strrchr(argv0, '\\');
#endif
g_program_invocation_short_name = slash ? slash + 1 : argv0;
#ifdef HAVE_STACKTRACE
InstallFailureFunction(&DumpStackTraceAndExit);
#endif
}
void ShutdownGoogleLoggingUtilities() {
CHECK(IsGoogleLoggingInitialized())
<< "You called ShutdownGoogleLogging() without calling InitGoogleLogging() first!";
g_program_invocation_short_name = NULL;
#ifdef HAVE_SYSLOG_H
closelog();
#endif
}
} // namespace glog_internal_namespace_
_END_GOOGLE_NAMESPACE_
// Make an implementation of stacktrace compiled.
#ifdef STACKTRACE_H
# include STACKTRACE_H
# if 0
// For include scanners which can't handle macro expansions.
# include "stacktrace_libunwind-inl.h"
# include "stacktrace_x86-inl.h"
# include "stacktrace_x86_64-inl.h"
# include "stacktrace_powerpc-inl.h"
# include "stacktrace_generic-inl.h"
# endif
#endif

238
third_party/glog/src/utilities.h vendored Normal file
View file

@ -0,0 +1,238 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Shinichiro Hamaji
//
// Define utilties for glog internal usage.
#ifndef UTILITIES_H__
#define UTILITIES_H__
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# define OS_WINDOWS
#elif defined(__CYGWIN__) || defined(__CYGWIN32__)
# define OS_CYGWIN
#elif defined(linux) || defined(__linux) || defined(__linux__)
# ifndef OS_LINUX
# define OS_LINUX
# endif
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define OS_MACOSX
#elif defined(__FreeBSD__)
# define OS_FREEBSD
#elif defined(__NetBSD__)
# define OS_NETBSD
#elif defined(__OpenBSD__)
# define OS_OPENBSD
#else
// TODO(hamaji): Add other platforms.
#endif
// printf macros for size_t, in the style of inttypes.h
#ifdef _LP64
#define __PRIS_PREFIX "z"
#else
#define __PRIS_PREFIX
#endif
// Use these macros after a % in a printf format string
// to get correct 32/64 bit behavior, like this:
// size_t size = records.size();
// printf("%"PRIuS"\n", size);
#define PRIdS __PRIS_PREFIX "d"
#define PRIxS __PRIS_PREFIX "x"
#define PRIuS __PRIS_PREFIX "u"
#define PRIXS __PRIS_PREFIX "X"
#define PRIoS __PRIS_PREFIX "o"
#include "base/mutex.h" // This must go first so we get _XOPEN_SOURCE
#include <string>
#if defined(OS_WINDOWS)
# include "port.h"
#endif
#include "config.h"
#include "glog/logging.h"
// There are three different ways we can try to get the stack trace:
//
// 1) The libunwind library. This is still in development, and as a
// separate library adds a new dependency, but doesn't need a frame
// pointer. It also doesn't call malloc.
//
// 2) Our hand-coded stack-unwinder. This depends on a certain stack
// layout, which is used by gcc (and those systems using a
// gcc-compatible ABI) on x86 systems, at least since gcc 2.95.
// It uses the frame pointer to do its work.
//
// 3) The gdb unwinder -- also the one used by the c++ exception code.
// It's obviously well-tested, but has a fatal flaw: it can call
// malloc() from the unwinder. This is a problem because we're
// trying to use the unwinder to instrument malloc().
//
// 4) The Windows API CaptureStackTrace.
//
// Note: if you add a new implementation here, make sure it works
// correctly when GetStackTrace() is called with max_depth == 0.
// Some code may do that.
#if defined(HAVE_LIB_UNWIND)
# define STACKTRACE_H "stacktrace_libunwind-inl.h"
#elif !defined(NO_FRAME_POINTER)
# if defined(__i386__) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_x86-inl.h"
# elif defined(__x86_64__) && __GNUC__ >= 2 && HAVE_UNWIND_H
# define STACKTRACE_H "stacktrace_x86_64-inl.h"
# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_powerpc-inl.h"
# elif defined(OS_WINDOWS)
# define STACKTRACE_H "stacktrace_windows-inl.h"
# endif
#endif
#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_H)
# define STACKTRACE_H "stacktrace_generic-inl.h"
#endif
#if defined(STACKTRACE_H)
# define HAVE_STACKTRACE
#endif
#ifndef HAVE_SYMBOLIZE
// defined by gcc
#if defined(__ELF__) && defined(OS_LINUX)
# define HAVE_SYMBOLIZE
#elif defined(OS_MACOSX) && defined(HAVE_DLADDR)
// Use dladdr to symbolize.
# define HAVE_SYMBOLIZE
#elif defined(OS_WINDOWS)
// Use DbgHelp to symbolize
# define HAVE_SYMBOLIZE
#endif
#endif // !defined(HAVE_SYMBOLIZE)
#ifndef ARRAYSIZE
// There is a better way, but this is good enough for our purpose.
# define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
#endif
_START_GOOGLE_NAMESPACE_
namespace glog_internal_namespace_ {
#ifdef HAVE___ATTRIBUTE__
# define ATTRIBUTE_NOINLINE __attribute__ ((noinline))
# define HAVE_ATTRIBUTE_NOINLINE
#elif defined(OS_WINDOWS)
# define ATTRIBUTE_NOINLINE __declspec(noinline)
# define HAVE_ATTRIBUTE_NOINLINE
#else
# define ATTRIBUTE_NOINLINE
#endif
const char* ProgramInvocationShortName();
bool IsGoogleLoggingInitialized();
int64 CycleClock_Now();
int64 UsecToCycles(int64 usec);
typedef double WallTime;
WallTime WallTime_Now();
int32 GetMainThreadPid();
bool PidHasChanged();
pid_t GetTID();
const std::string& MyUserName();
// Get the part of filepath after the last path separator.
// (Doesn't modify filepath, contrary to basename() in libgen.h.)
const char* const_basename(const char* filepath);
// Wrapper of __sync_val_compare_and_swap. If the GCC extension isn't
// defined, we try the CPU specific logics (we only support x86 and
// x86_64 for now) first, then use a naive implementation, which has a
// race condition.
template<typename T>
inline T sync_val_compare_and_swap(T* ptr, T oldval, T newval) {
#if defined(HAVE___SYNC_VAL_COMPARE_AND_SWAP)
return __sync_val_compare_and_swap(ptr, oldval, newval);
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
T ret;
__asm__ __volatile__("lock; cmpxchg %1, (%2);"
:"=a"(ret)
// GCC may produces %sil or %dil for
// constraint "r", but some of apple's gas
// dosn't know the 8 bit registers.
// We use "q" to avoid these registers.
:"q"(newval), "q"(ptr), "a"(oldval)
:"memory", "cc");
return ret;
#else
T ret = *ptr;
if (ret == oldval) {
*ptr = newval;
}
return ret;
#endif
}
void DumpStackTraceToString(std::string* stacktrace);
struct CrashReason {
CrashReason() : filename(0), line_number(0), message(0), depth(0) {}
const char* filename;
int line_number;
const char* message;
// We'll also store a bit of stack trace context at the time of crash as
// it may not be available later on.
void* stack[32];
int depth;
};
void SetCrashReason(const CrashReason* r);
void InitGoogleLoggingUtilities(const char* argv0);
void ShutdownGoogleLoggingUtilities();
} // namespace glog_internal_namespace_
_END_GOOGLE_NAMESPACE_
using namespace GOOGLE_NAMESPACE::glog_internal_namespace_;
#endif // UTILITIES_H__

View file

@ -0,0 +1,58 @@
// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Shinichiro Hamaji
#include "utilities.h"
#include "googletest.h"
#include "glog/logging.h"
#ifdef HAVE_LIB_GFLAGS
#include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE;
#endif
using namespace GOOGLE_NAMESPACE;
TEST(utilities, sync_val_compare_and_swap) {
bool now_entering = false;
EXPECT_FALSE(sync_val_compare_and_swap(&now_entering, false, true));
EXPECT_TRUE(sync_val_compare_and_swap(&now_entering, false, true));
EXPECT_TRUE(sync_val_compare_and_swap(&now_entering, false, true));
}
TEST(utilities, InitGoogleLoggingDeathTest) {
ASSERT_DEATH(InitGoogleLogging("foobar"), "");
}
int main(int argc, char **argv) {
InitGoogleLogging(argv[0]);
InitGoogleTest(&argc, argv);
CHECK_EQ(RUN_ALL_TESTS(), 0);
}

257
third_party/glog/src/vlog_is_on.cc vendored Normal file
View file

@ -0,0 +1,257 @@
// Copyright (c) 1999, 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Ray Sidney and many others
//
// Broken out from logging.cc by Soren Lassen
// logging_unittest.cc covers the functionality herein
#include "utilities.h"
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <cstdio>
#include <string>
#include "base/commandlineflags.h"
#include "glog/logging.h"
#include "glog/raw_logging.h"
#include "base/googleinit.h"
// glog doesn't have annotation
#define ANNOTATE_BENIGN_RACE(address, description)
using std::string;
GLOG_DEFINE_int32(v, 0, "Show all VLOG(m) messages for m <= this."
" Overridable by --vmodule.");
GLOG_DEFINE_string(vmodule, "", "per-module verbose level."
" Argument is a comma-separated list of <module name>=<log level>."
" <module name> is a glob pattern, matched against the filename base"
" (that is, name ignoring .cc/.h./-inl.h)."
" <log level> overrides any value given by --v.");
_START_GOOGLE_NAMESPACE_
namespace glog_internal_namespace_ {
// Used by logging_unittests.cc so can't make it static here.
GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
size_t patt_len,
const char* str,
size_t str_len);
// Implementation of fnmatch that does not need 0-termination
// of arguments and does not allocate any memory,
// but we only support "*" and "?" wildcards, not the "[...]" patterns.
// It's not a static function for the unittest.
GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
size_t patt_len,
const char* str,
size_t str_len) {
size_t p = 0;
size_t s = 0;
while (1) {
if (p == patt_len && s == str_len) return true;
if (p == patt_len) return false;
if (s == str_len) return p+1 == patt_len && pattern[p] == '*';
if (pattern[p] == str[s] || pattern[p] == '?') {
p += 1;
s += 1;
continue;
}
if (pattern[p] == '*') {
if (p+1 == patt_len) return true;
do {
if (SafeFNMatch_(pattern+(p+1), patt_len-(p+1), str+s, str_len-s)) {
return true;
}
s += 1;
} while (s != str_len);
return false;
}
return false;
}
}
} // namespace glog_internal_namespace_
using glog_internal_namespace_::SafeFNMatch_;
int32 kLogSiteUninitialized = 1000;
// List of per-module log levels from FLAGS_vmodule.
// Once created each element is never deleted/modified
// except for the vlog_level: other threads will read VModuleInfo blobs
// w/o locks and we'll store pointers to vlog_level at VLOG locations
// that will never go away.
// We can't use an STL struct here as we wouldn't know
// when it's safe to delete/update it: other threads need to use it w/o locks.
struct VModuleInfo {
string module_pattern;
mutable int32 vlog_level; // Conceptually this is an AtomicWord, but it's
// too much work to use AtomicWord type here
// w/o much actual benefit.
const VModuleInfo* next;
};
// This protects the following global variables.
static Mutex vmodule_lock;
// Pointer to head of the VModuleInfo list.
// It's a map from module pattern to logging level for those module(s).
static VModuleInfo* vmodule_list = 0;
// Boolean initialization flag.
static bool inited_vmodule = false;
// L >= vmodule_lock.
static void VLOG2Initializer() {
vmodule_lock.AssertHeld();
// Can now parse --vmodule flag and initialize mapping of module-specific
// logging levels.
inited_vmodule = false;
const char* vmodule = FLAGS_vmodule.c_str();
const char* sep;
VModuleInfo* head = NULL;
VModuleInfo* tail = NULL;
while ((sep = strchr(vmodule, '=')) != NULL) {
string pattern(vmodule, sep - vmodule);
int module_level;
if (sscanf(sep, "=%d", &module_level) == 1) {
VModuleInfo* info = new VModuleInfo;
info->module_pattern = pattern;
info->vlog_level = module_level;
if (head) tail->next = info;
else head = info;
tail = info;
}
// Skip past this entry
vmodule = strchr(sep, ',');
if (vmodule == NULL) break;
vmodule++; // Skip past ","
}
if (head) { // Put them into the list at the head:
tail->next = vmodule_list;
vmodule_list = head;
}
inited_vmodule = true;
}
// This can be called very early, so we use SpinLock and RAW_VLOG here.
int SetVLOGLevel(const char* module_pattern, int log_level) {
int result = FLAGS_v;
int const pattern_len = strlen(module_pattern);
bool found = false;
{
MutexLock l(&vmodule_lock); // protect whole read-modify-write
for (const VModuleInfo* info = vmodule_list;
info != NULL; info = info->next) {
if (info->module_pattern == module_pattern) {
if (!found) {
result = info->vlog_level;
found = true;
}
info->vlog_level = log_level;
} else if (!found &&
SafeFNMatch_(info->module_pattern.c_str(),
info->module_pattern.size(),
module_pattern, pattern_len)) {
result = info->vlog_level;
found = true;
}
}
if (!found) {
VModuleInfo* info = new VModuleInfo;
info->module_pattern = module_pattern;
info->vlog_level = log_level;
info->next = vmodule_list;
vmodule_list = info;
}
}
RAW_VLOG(1, "Set VLOG level for \"%s\" to %d", module_pattern, log_level);
return result;
}
// NOTE: Individual VLOG statements cache the integer log level pointers.
// NOTE: This function must not allocate memory or require any locks.
bool InitVLOG3__(int32** site_flag, int32* site_default,
const char* fname, int32 verbose_level) {
MutexLock l(&vmodule_lock);
bool read_vmodule_flag = inited_vmodule;
if (!read_vmodule_flag) {
VLOG2Initializer();
}
// protect the errno global in case someone writes:
// VLOG(..) << "The last error was " << strerror(errno)
int old_errno = errno;
// site_default normally points to FLAGS_v
int32* site_flag_value = site_default;
// Get basename for file
const char* base = strrchr(fname, '/');
base = base ? (base+1) : fname;
const char* base_end = strchr(base, '.');
size_t base_length = base_end ? size_t(base_end - base) : strlen(base);
// Trim out trailing "-inl" if any
if (base_length >= 4 && (memcmp(base+base_length-4, "-inl", 4) == 0)) {
base_length -= 4;
}
// TODO: Trim out _unittest suffix? Perhaps it is better to have
// the extra control and just leave it there.
// find target in vector of modules, replace site_flag_value with
// a module-specific verbose level, if any.
for (const VModuleInfo* info = vmodule_list;
info != NULL; info = info->next) {
if (SafeFNMatch_(info->module_pattern.c_str(), info->module_pattern.size(),
base, base_length)) {
site_flag_value = &info->vlog_level;
// value at info->vlog_level is now what controls
// the VLOG at the caller site forever
break;
}
}
// Cache the vlog value pointer if --vmodule flag has been parsed.
ANNOTATE_BENIGN_RACE(site_flag,
"*site_flag may be written by several threads,"
" but the value will be the same");
if (read_vmodule_flag) *site_flag = site_flag_value;
// restore the errno in case something recoverable went wrong during
// the initialization of the VLOG mechanism (see above note "protect the..")
errno = old_errno;
return *site_flag_value >= verbose_level;
}
_END_GOOGLE_NAMESPACE_

21
third_party/glog/src/windows/config.h vendored Executable file
View file

@ -0,0 +1,21 @@
/* src/config.h.in. Generated from configure.ac by autoheader. */
/* Namespace for Google classes */
#define GOOGLE_NAMESPACE google
/* Stops putting the code inside the Google namespace */
#define _END_GOOGLE_NAMESPACE_ }
/* Puts following code inside the Google namespace */
#define _START_GOOGLE_NAMESPACE_ namespace google {
/* Always the empty-string on non-windows systems. On windows, should be
"__declspec(dllexport)". This way, when we compile the dll, we export our
functions/classes. It's safe to define this here because config.h is only
used internally, to compile the DLL, and every DLL source file #includes
"config.h" before anything else. */
#ifndef GOOGLE_GLOG_DLL_DECL
# define GOOGLE_GLOG_IS_A_DLL 1 /* not set if you're statically linking */
# define GOOGLE_GLOG_DLL_DECL __declspec(dllexport)
# define GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS __declspec(dllimport)
#endif

1160
third_party/glog/src/windows/dirent.h vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,96 @@
// This file is automatically generated from src/glog/log_severity.h
// using src/windows/preprocess.sh.
// DO NOT EDIT!
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_LOG_SEVERITY_H__
#define BASE_LOG_SEVERITY_H__
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
// Variables of type LogSeverity are widely taken to lie in the range
// [0, NUM_SEVERITIES-1]. Be careful to preserve this assumption if
// you ever need to change their values or add a new severity.
typedef int LogSeverity;
const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
NUM_SEVERITIES = 4;
#ifndef GLOG_NO_ABBREVIATED_SEVERITIES
# ifdef ERROR
# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
# endif
const int INFO = GLOG_INFO, WARNING = GLOG_WARNING,
ERROR = GLOG_ERROR, FATAL = GLOG_FATAL;
#endif
// DFATAL is FATAL in debug mode, ERROR in normal mode
#ifdef NDEBUG
#define DFATAL_LEVEL ERROR
#else
#define DFATAL_LEVEL FATAL
#endif
extern GOOGLE_GLOG_DLL_DECL const char* const LogSeverityNames[NUM_SEVERITIES];
// NDEBUG usage helpers related to (RAW_)DCHECK:
//
// DEBUG_MODE is for small !NDEBUG uses like
// if (DEBUG_MODE) foo.CheckThatFoo();
// instead of substantially more verbose
// #ifndef NDEBUG
// foo.CheckThatFoo();
// #endif
//
// IF_DEBUG_MODE is for small !NDEBUG uses like
// IF_DEBUG_MODE( string error; )
// DCHECK(Foo(&error)) << error;
// instead of substantially more verbose
// #ifndef NDEBUG
// string error;
// DCHECK(Foo(&error)) << error;
// #endif
//
#ifdef NDEBUG
enum { DEBUG_MODE = 0 };
#define IF_DEBUG_MODE(x)
#else
enum { DEBUG_MODE = 1 };
#define IF_DEBUG_MODE(x) x
#endif
#endif // BASE_LOG_SEVERITY_H__

1690
third_party/glog/src/windows/glog/logging.h vendored Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,184 @@
// This file is automatically generated from src/glog/raw_logging.h.in
// using src/windows/preprocess.sh.
// DO NOT EDIT!
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Maxim Lifantsev
//
// Thread-safe logging routines that do not allocate any memory or
// acquire any locks, and can therefore be used by low-level memory
// allocation and synchronization code.
#ifndef BASE_RAW_LOGGING_H_
#define BASE_RAW_LOGGING_H_
#include <time.h>
namespace google {
#include "glog/log_severity.h"
#include "glog/vlog_is_on.h"
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
// This is similar to LOG(severity) << format... and VLOG(level) << format..,
// but
// * it is to be used ONLY by low-level modules that can't use normal LOG()
// * it is desiged to be a low-level logger that does not allocate any
// memory and does not need any locks, hence:
// * it logs straight and ONLY to STDERR w/o buffering
// * it uses an explicit format and arguments list
// * it will silently chop off really long message strings
// Usage example:
// RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
// RAW_VLOG(3, "status is %i", status);
// These will print an almost standard log lines like this to stderr only:
// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
// I0821 211317 file.cc:142] RAW: status is 20
#define RAW_LOG(severity, ...) \
do { \
switch (google::GLOG_ ## severity) { \
case 0: \
RAW_LOG_INFO(__VA_ARGS__); \
break; \
case 1: \
RAW_LOG_WARNING(__VA_ARGS__); \
break; \
case 2: \
RAW_LOG_ERROR(__VA_ARGS__); \
break; \
case 3: \
RAW_LOG_FATAL(__VA_ARGS__); \
break; \
default: \
break; \
} \
} while (0)
// The following STRIP_LOG testing is performed in the header file so that it's
// possible to completely compile out the logging code and the log messages.
#if STRIP_LOG == 0
#define RAW_VLOG(verboselevel, ...) \
do { \
if (VLOG_IS_ON(verboselevel)) { \
RAW_LOG_INFO(__VA_ARGS__); \
} \
} while (0)
#else
#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
#if STRIP_LOG == 0
#define RAW_LOG_INFO(...) google::RawLog__(google::GLOG_INFO, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_INFO(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
#if STRIP_LOG <= 1
#define RAW_LOG_WARNING(...) google::RawLog__(google::GLOG_WARNING, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_WARNING(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 1
#if STRIP_LOG <= 2
#define RAW_LOG_ERROR(...) google::RawLog__(google::GLOG_ERROR, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_ERROR(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 2
#if STRIP_LOG <= 3
#define RAW_LOG_FATAL(...) google::RawLog__(google::GLOG_FATAL, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_FATAL(...) \
do { \
google::RawLogStub__(0, __VA_ARGS__); \
exit(1); \
} while (0)
#endif // STRIP_LOG <= 3
// Similar to CHECK(condition) << message,
// but for low-level modules: we use only RAW_LOG that does not allocate memory.
// We do not want to provide args list here to encourage this usage:
// if (!cond) RAW_LOG(FATAL, "foo ...", hard_to_compute_args);
// so that the args are not computed when not needed.
#define RAW_CHECK(condition, message) \
do { \
if (!(condition)) { \
RAW_LOG(FATAL, "Check %s failed: %s", #condition, message); \
} \
} while (0)
// Debug versions of RAW_LOG and RAW_CHECK
#ifndef NDEBUG
#define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__)
#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message)
#else // NDEBUG
#define RAW_DLOG(severity, ...) \
while (false) \
RAW_LOG(severity, __VA_ARGS__)
#define RAW_DCHECK(condition, message) \
while (false) \
RAW_CHECK(condition, message)
#endif // NDEBUG
// Stub log function used to work around for unused variable warnings when
// building with STRIP_LOG > 0.
static inline void RawLogStub__(int /* ignored */, ...) {
}
// Helper function to implement RAW_LOG and RAW_VLOG
// Logs format... at "severity" level, reporting it
// as called from file:line.
// This does not allocate memory or acquire locks.
GOOGLE_GLOG_DLL_DECL void RawLog__(LogSeverity severity,
const char* file,
int line,
const char* format, ...)
;
}
#endif // BASE_RAW_LOGGING_H_

View file

@ -0,0 +1,224 @@
// This file is automatically generated from src/glog/stl_logging.h.in
// using src/windows/preprocess.sh.
// DO NOT EDIT!
// Copyright (c) 2003, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Stream output operators for STL containers; to be used for logging *only*.
// Inclusion of this file lets you do:
//
// list<string> x;
// LOG(INFO) << "data: " << x;
// vector<int> v1, v2;
// CHECK_EQ(v1, v2);
//
// If you want to use this header file with hash_compare maps or slist, you
// need to define macros before including this file:
//
// - GLOG_STL_LOGGING_FOR_UNORDERED - <unordered_map> and <unordered_set>
// - GLOG_STL_LOGGING_FOR_TR1_UNORDERED - <tr1/unordered_(map|set)>
// - GLOG_STL_LOGGING_FOR_EXT_HASH - <ext/hash_(map|set)>
// - GLOG_STL_LOGGING_FOR_EXT_SLIST - <ext/slist>
//
#ifndef UTIL_GTL_STL_LOGGING_INL_H_
#define UTIL_GTL_STL_LOGGING_INL_H_
#if !1
# error We do not support stl_logging for this compiler
#endif
#include <deque>
#include <list>
#include <map>
#include <ostream>
#include <set>
#include <utility>
#include <vector>
#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
# include <unordered_map>
# include <unordered_set>
#endif
#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
# include <tr1/unordered_map>
# include <tr1/unordered_set>
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
# include <ext/hash_set>
# include <ext/hash_map>
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
# include <ext/slist>
#endif
// Forward declare these two, and define them after all the container streams
// operators so that we can recurse from pair -> container -> container -> pair
// properly.
template<class First, class Second>
std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
namespace google {
template<class Iter>
void PrintSequence(std::ostream& out, Iter begin, Iter end);
}
#define OUTPUT_TWO_ARG_CONTAINER(Sequence) \
template<class T1, class T2> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2>& seq) { \
google::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
OUTPUT_TWO_ARG_CONTAINER(std::vector)
OUTPUT_TWO_ARG_CONTAINER(std::deque)
OUTPUT_TWO_ARG_CONTAINER(std::list)
#ifdef GLOG_STL_LOGGING_FOR_EXT_SLIST
OUTPUT_TWO_ARG_CONTAINER(__gnu_cxx::slist)
#endif
#undef OUTPUT_TWO_ARG_CONTAINER
#define OUTPUT_THREE_ARG_CONTAINER(Sequence) \
template<class T1, class T2, class T3> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2, T3>& seq) { \
google::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
OUTPUT_THREE_ARG_CONTAINER(std::set)
OUTPUT_THREE_ARG_CONTAINER(std::multiset)
#undef OUTPUT_THREE_ARG_CONTAINER
#define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \
template<class T1, class T2, class T3, class T4> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2, T3, T4>& seq) { \
google::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
OUTPUT_FOUR_ARG_CONTAINER(std::map)
OUTPUT_FOUR_ARG_CONTAINER(std::multimap)
#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
OUTPUT_FOUR_ARG_CONTAINER(std::unordered_set)
OUTPUT_FOUR_ARG_CONTAINER(std::unordered_multiset)
#endif
#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_set)
OUTPUT_FOUR_ARG_CONTAINER(std::tr1::unordered_multiset)
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_set)
OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_multiset)
#endif
#undef OUTPUT_FOUR_ARG_CONTAINER
#define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \
template<class T1, class T2, class T3, class T4, class T5> \
inline std::ostream& operator<<(std::ostream& out, \
const Sequence<T1, T2, T3, T4, T5>& seq) { \
google::PrintSequence(out, seq.begin(), seq.end()); \
return out; \
}
#ifdef GLOG_STL_LOGGING_FOR_UNORDERED
OUTPUT_FIVE_ARG_CONTAINER(std::unordered_map)
OUTPUT_FIVE_ARG_CONTAINER(std::unordered_multimap)
#endif
#ifdef GLOG_STL_LOGGING_FOR_TR1_UNORDERED
OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_map)
OUTPUT_FIVE_ARG_CONTAINER(std::tr1::unordered_multimap)
#endif
#ifdef GLOG_STL_LOGGING_FOR_EXT_HASH
OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_map)
OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_multimap)
#endif
#undef OUTPUT_FIVE_ARG_CONTAINER
template<class First, class Second>
inline std::ostream& operator<<(std::ostream& out,
const std::pair<First, Second>& p) {
out << '(' << p.first << ", " << p.second << ')';
return out;
}
namespace google {
template<class Iter>
inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
// Output at most 100 elements -- appropriate if used for logging.
for (int i = 0; begin != end && i < 100; ++i, ++begin) {
if (i > 0) out << ' ';
out << *begin;
}
if (begin != end) {
out << " ...";
}
}
}
// Note that this is technically undefined behavior! We are adding things into
// the std namespace for a reason though -- we are providing new operations on
// types which are themselves defined with this namespace. Without this, these
// operator overloads cannot be found via ADL. If these definitions are not
// found via ADL, they must be #included before they're used, which requires
// this header to be included before apparently independent other headers.
//
// For example, base/logging.h defines various template functions to implement
// CHECK_EQ(x, y) and stream x and y into the log in the event the check fails.
// It does so via the function template MakeCheckOpValueString:
// template<class T>
// void MakeCheckOpValueString(strstream* ss, const T& v) {
// (*ss) << v;
// }
// Because 'glog/logging.h' is included before 'glog/stl_logging.h',
// subsequent CHECK_EQ(v1, v2) for vector<...> typed variable v1 and v2 can only
// find these operator definitions via ADL.
//
// Even this solution has problems -- it may pull unintended operators into the
// namespace as well, allowing them to also be found via ADL, and creating code
// that only works with a particular order of includes. Long term, we need to
// move all of the *definitions* into namespace std, bet we need to ensure no
// one references them first. This lets us take that step. We cannot define them
// in both because that would create ambiguous overloads when both are found.
namespace std { using ::operator<<; }
#endif // UTIL_GTL_STL_LOGGING_INL_H_

133
third_party/glog/src/windows/glog/vlog_is_on.h vendored Executable file
View file

@ -0,0 +1,133 @@
// This file is automatically generated from src/glog/vlog_is_on.h.in
// using src/windows/preprocess.sh.
// DO NOT EDIT!
// Copyright (c) 1999, 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Ray Sidney and many others
//
// Defines the VLOG_IS_ON macro that controls the variable-verbosity
// conditional logging.
//
// It's used by VLOG and VLOG_IF in logging.h
// and by RAW_VLOG in raw_logging.h to trigger the logging.
//
// It can also be used directly e.g. like this:
// if (VLOG_IS_ON(2)) {
// // do some logging preparation and logging
// // that can't be accomplished e.g. via just VLOG(2) << ...;
// }
//
// The truth value that VLOG_IS_ON(level) returns is determined by
// the three verbosity level flags:
// --v=<n> Gives the default maximal active V-logging level;
// 0 is the default.
// Normally positive values are used for V-logging levels.
// --vmodule=<str> Gives the per-module maximal V-logging levels to override
// the value given by --v.
// E.g. "my_module=2,foo*=3" would change the logging level
// for all code in source files "my_module.*" and "foo*.*"
// ("-inl" suffixes are also disregarded for this matching).
//
// SetVLOGLevel helper function is provided to do limited dynamic control over
// V-logging by overriding the per-module settings given via --vmodule flag.
//
// CAVEAT: --vmodule functionality is not available in non gcc compilers.
//
#ifndef BASE_VLOG_IS_ON_H_
#define BASE_VLOG_IS_ON_H_
#include "glog/log_severity.h"
// Annoying stuff for windows -- makes sure clients can import these functions
#ifndef GOOGLE_GLOG_DLL_DECL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport)
# else
# define GOOGLE_GLOG_DLL_DECL
# endif
#endif
#if defined(__GNUC__)
// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site.
// (Normally) the first time every VLOG_IS_ON(n) site is hit,
// we determine what variable will dynamically control logging at this site:
// it's either FLAGS_v or an appropriate internal variable
// matching the current source file that represents results of
// parsing of --vmodule flag and/or SetVLOGLevel calls.
#define VLOG_IS_ON(verboselevel) \
__extension__ \
({ static google::int32* vlocal__ = &google::kLogSiteUninitialized; \
google::int32 verbose_level__ = (verboselevel); \
(*vlocal__ >= verbose_level__) && \
((vlocal__ != &google::kLogSiteUninitialized) || \
(google::InitVLOG3__(&vlocal__, &FLAGS_v, \
__FILE__, verbose_level__))); })
#else
// GNU extensions not available, so we do not support --vmodule.
// Dynamic value of FLAGS_v always controls the logging level.
#define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel))
#endif
// Set VLOG(_IS_ON) level for module_pattern to log_level.
// This lets us dynamically control what is normally set by the --vmodule flag.
// Returns the level that previously applied to module_pattern.
// NOTE: To change the log level for VLOG(_IS_ON) sites
// that have already executed after/during InitGoogleLogging,
// one needs to supply the exact --vmodule pattern that applied to them.
// (If no --vmodule pattern applied to them
// the value of FLAGS_v will continue to control them.)
extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern,
int log_level);
// Various declarations needed for VLOG_IS_ON above: =========================
// Special value used to indicate that a VLOG_IS_ON site has not been
// initialized. We make this a large value, so the common-case check
// of "*vlocal__ >= verbose_level__" in VLOG_IS_ON definition
// passes in such cases and InitVLOG3__ is then triggered.
extern google::int32 kLogSiteUninitialized;
// Helper routine which determines the logging info for a particalur VLOG site.
// site_flag is the address of the site-local pointer to the controlling
// verbosity level
// site_default is the default to use for *site_flag
// fname is the current source file name
// verbose_level is the argument to VLOG_IS_ON
// We will return the return value for VLOG_IS_ON
// and if possible set *site_flag appropriately.
extern GOOGLE_GLOG_DLL_DECL bool InitVLOG3__(
google::int32** site_flag,
google::int32* site_default,
const char* fname,
google::int32 verbose_level);
#endif // BASE_VLOG_IS_ON_H_

65
third_party/glog/src/windows/port.cc vendored Executable file
View file

@ -0,0 +1,65 @@
/* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ---
* Author: Craig Silverstein
* Copied from google-perftools and modified by Shinichiro Hamaji
*/
#ifndef _WIN32
# error You should only be including windows/port.cc in a windows environment!
#endif
#include "config.h"
#include <stdarg.h> // for va_list, va_start, va_end
#include "port.h"
// These call the windows _vsnprintf, but always NUL-terminate.
int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
if (size == 0) // not even room for a \0?
return -1; // not what C99 says to do, but what windows does
str[size-1] = '\0';
return _vsnprintf(str, size-1, format, ap);
}
#ifndef HAVE_LOCALTIME_R
struct tm* localtime_r(const time_t* timep, struct tm* result) {
localtime_s(result, timep);
return result;
}
#endif // not HAVE_LOCALTIME_R
#ifndef HAVE_SNPRINTF
int snprintf(char *str, size_t size, const char *format, ...) {
va_list ap;
va_start(ap, format);
const int r = vsnprintf(str, size, format, ap);
va_end(ap);
return r;
}
#endif

174
third_party/glog/src/windows/port.h vendored Executable file
View file

@ -0,0 +1,174 @@
/* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ---
* Author: Craig Silverstein
* Copied from google-perftools and modified by Shinichiro Hamaji
*
* These are some portability typedefs and defines to make it a bit
* easier to compile this code under VC++.
*
* Several of these are taken from glib:
* http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
*/
#ifndef CTEMPLATE_WINDOWS_PORT_H_
#define CTEMPLATE_WINDOWS_PORT_H_
#include "config.h"
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
#endif
#include <windows.h>
#include <winsock.h> /* for gethostname */
#include <io.h> /* because we so often use open/close/etc */
#include <direct.h> /* for _getcwd() */
#include <process.h> /* for _getpid() */
#include <stdio.h> /* read in vsnprintf decl. before redifining it */
#include <stdarg.h> /* template_dictionary.cc uses va_copy */
#include <string.h> /* for _strnicmp(), strerror_s() */
#include <time.h> /* for localtime_s() */
/* Note: the C++ #includes are all together at the bottom. This file is
* used by both C and C++ code, so we put all the C++ together.
*/
#ifdef _MSC_VER
/* 4244: otherwise we get problems when substracting two size_t's to an int
* 4251: it's complaining about a private struct I've chosen not to dllexport
* 4355: we use this in a constructor, but we do it safely
* 4715: for some reason VC++ stopped realizing you can't return after abort()
* 4800: we know we're casting ints/char*'s to bools, and we're ok with that
* 4996: Yes, we're ok using "unsafe" functions like fopen() and strerror()
* 4312: Converting uint32_t to a pointer when testing %p
* 4267: also subtracting two size_t to int
* 4722: Destructor never returns due to abort()
*/
#pragma warning(disable:4244 4251 4355 4715 4800 4996 4267 4312 4722)
/* file I/O */
#define PATH_MAX 1024
#define access _access
#define getcwd _getcwd
#define open _open
#define read _read
#define write _write
#define lseek _lseek
#define close _close
#define popen _popen
#define pclose _pclose
#define R_OK 04 /* read-only (for access()) */
#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
#define O_WRONLY _O_WRONLY
#define O_CREAT _O_CREAT
#define O_EXCL _O_EXCL
#ifndef __MINGW32__
enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
#endif
#define S_IRUSR S_IREAD
#define S_IWUSR S_IWRITE
/* Not quite as lightweight as a hard-link, but more than good enough for us. */
#define link(oldpath, newpath) CopyFileA(oldpath, newpath, false)
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
/* In windows-land, hash<> is called hash_compare<> (from xhash.h) */
/* VC11 provides std::hash */
#if defined(_MSC_VER) && (_MSC_VER < 1700)
#define hash hash_compare
#endif
/* Sleep is in ms, on windows */
#define sleep(secs) Sleep((secs) * 1000)
/* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
* because they don't always NUL-terminate. :-( We also can't use the
* name vsnprintf, since windows defines that (but not snprintf (!)).
*/
#ifndef HAVE_SNPRINTF
extern int GOOGLE_GLOG_DLL_DECL snprintf(char *str, size_t size,
const char *format, ...);
#endif
extern int GOOGLE_GLOG_DLL_DECL safe_vsnprintf(char *str, size_t size,
const char *format, va_list ap);
#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
#ifndef va_copy
#define va_copy(dst, src) (dst) = (src)
#endif
/* Windows doesn't support specifying the number of buckets as a
* hash_map constructor arg, so we leave this blank.
*/
#define CTEMPLATE_SMALL_HASHTABLE
#define DEFAULT_TEMPLATE_ROOTDIR ".."
// ----------------------------------- SYSTEM/PROCESS
typedef int pid_t;
#define getpid _getpid
#endif // _MSC_VER
// ----------------------------------- THREADS
#if defined(HAVE_PTHREAD)
# include <pthread.h>
#else // no PTHREAD
typedef DWORD pthread_t;
typedef DWORD pthread_key_t;
typedef LONG pthread_once_t;
enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock
#define pthread_self GetCurrentThreadId
#define pthread_equal(pthread_t_1, pthread_t_2) ((pthread_t_1)==(pthread_t_2))
#endif // HAVE_PTHREAD
#ifndef HAVE_LOCALTIME_R
extern GOOGLE_GLOG_DLL_DECL struct tm* localtime_r(const time_t* timep, struct tm* result);
#endif // not HAVE_LOCALTIME_R
inline char* strerror_r(int errnum, char* buf, size_t buflen) {
strerror_s(buf, buflen, errnum);
return buf;
}
#ifndef __cplusplus
/* I don't see how to get inlining for C code in MSVC. Ah well. */
#define inline
#endif
#endif /* _WIN32 */
#endif /* CTEMPLATE_WINDOWS_PORT_H_ */

119
third_party/glog/src/windows/preprocess.sh vendored Executable file
View file

@ -0,0 +1,119 @@
#!/bin/sh
# Copyright (c) 2008, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ---
# Author: Craig Silverstein
# Copied from google-perftools and modified by Shinichiro Hamaji
#
# This script is meant to be run at distribution-generation time, for
# instance by autogen.sh. It does some of the work configure would
# normally do, for windows systems. In particular, it expands all the
# @...@ variables found in .in files, and puts them here, in the windows
# directory.
#
# This script should be run before any new release.
if [ -z "$1" ]; then
echo "USAGE: $0 <src/ directory>"
exit 1
fi
DLLDEF_MACRO_NAME="GLOG_DLL_DECL"
# The text we put in every .h files we create. As a courtesy, we'll
# include a helpful comment for windows users as to how to use
# GLOG_DLL_DECL. Apparently sed expands \n into a newline. Good!
DLLDEF_DEFINES="\
// NOTE: if you are statically linking the template library into your binary\n\
// (rather than using the template .dll), set '/D $DLLDEF_MACRO_NAME='\n\
// as a compiler flag in your project file to turn off the dllimports.\n\
#ifndef $DLLDEF_MACRO_NAME\n\
# define $DLLDEF_MACRO_NAME __declspec(dllimport)\n\
#endif"
# Read all the windows config info into variables
# In order for the 'set' to take, this requires putting all in a subshell.
(
while read define varname value; do
[ "$define" != "#define" ] && continue
eval "$varname='$value'"
done
# Process all the .in files in the "glog" subdirectory
mkdir -p "$1/windows/glog"
for file in `echo "$1"/glog/*.in`; do
echo "Processing $file"
outfile="$1/windows/glog/`basename $file .in`"
echo "\
// This file is automatically generated from $file
// using src/windows/preprocess.sh.
// DO NOT EDIT!
" > "$outfile"
# Besides replacing @...@, we also need to turn on dllimport
# We also need to replace hash by hash_compare (annoying we hard-code :-( )
sed -e "s!@ac_windows_dllexport@!$DLLDEF_MACRO_NAME!g" \
-e "s!@ac_windows_dllexport_defines@!$DLLDEF_DEFINES!g" \
-e "s!@ac_cv_cxx_hash_map@!$HASH_MAP_H!g" \
-e "s!@ac_cv_cxx_hash_namespace@!$HASH_NAMESPACE!g" \
-e "s!@ac_cv_cxx_hash_set@!$HASH_SET_H!g" \
-e "s!@ac_cv_have_stdint_h@!0!g" \
-e "s!@ac_cv_have_systypes_h@!0!g" \
-e "s!@ac_cv_have_inttypes_h@!0!g" \
-e "s!@ac_cv_have_unistd_h@!0!g" \
-e "s!@ac_cv_have_uint16_t@!0!g" \
-e "s!@ac_cv_have_u_int16_t@!0!g" \
-e "s!@ac_cv_have___uint16@!1!g" \
-e "s!@ac_cv_have_libgflags@!0!g" \
-e "s!@ac_cv_have___builtin_expect@!0!g" \
-e "s!@ac_cv_cxx_using_operator@!1!g" \
-e "s!@ac_cv___attribute___noreturn@!__declspec(noreturn)!g" \
-e "s!@ac_cv___attribute___noinline@!!g" \
-e "s!@ac_cv___attribute___printf_4_5@!!g" \
-e "s!@ac_google_attribute@!${HAVE___ATTRIBUTE__:-0}!g" \
-e "s!@ac_google_end_namespace@!$_END_GOOGLE_NAMESPACE_!g" \
-e "s!@ac_google_namespace@!$GOOGLE_NAMESPACE!g" \
-e "s!@ac_google_start_namespace@!$_START_GOOGLE_NAMESPACE_!g" \
-e "s!@ac_htmlparser_namespace@!$HTMLPARSER_NAMESPACE!g" \
-e "s!\\bhash\\b!hash_compare!g" \
"$file" >> "$outfile"
done
) < "$1/windows/config.h"
# log_severity.h isn't a .in file.
echo "\
// This file is automatically generated from $1/glog/log_severity.h
// using src/windows/preprocess.sh.
// DO NOT EDIT!
" > "$1/windows/glog/log_severity.h"
cat "$1/glog/log_severity.h" >> "$1/windows/glog/log_severity.h"
echo "DONE"