merge(3p/glog): Vendor glog from commit 'afe04691'
This commit is contained in:
commit
6941048b7e
133 changed files with 23455 additions and 0 deletions
133
third_party/glog/src/base/commandlineflags.h
vendored
Normal file
133
third_party/glog/src/base/commandlineflags.h
vendored
Normal 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
51
third_party/glog/src/base/googleinit.h
vendored
Normal 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
333
third_party/glog/src/base/mutex.h
vendored
Normal 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
219
third_party/glog/src/config.h.cmake.in
vendored
Normal 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
|
||||
66
third_party/glog/src/config_for_unittests.h
vendored
Normal file
66
third_party/glog/src/config_for_unittests.h
vendored
Normal 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
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
85
third_party/glog/src/demangle.h
vendored
Normal 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_
|
||||
168
third_party/glog/src/demangle_unittest.cc
vendored
Normal file
168
third_party/glog/src/demangle_unittest.cc
vendored
Normal 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
95
third_party/glog/src/demangle_unittest.sh
vendored
Executable 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
|
||||
145
third_party/glog/src/demangle_unittest.txt
vendored
Normal file
145
third_party/glog/src/demangle_unittest.txt
vendored
Normal 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
107
third_party/glog/src/glog/log_severity.h
vendored
Normal 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
1689
third_party/glog/src/glog/logging.h.in
vendored
Normal file
File diff suppressed because it is too large
Load diff
180
third_party/glog/src/glog/raw_logging.h.in
vendored
Normal file
180
third_party/glog/src/glog/raw_logging.h.in
vendored
Normal 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_
|
||||
220
third_party/glog/src/glog/stl_logging.h.in
vendored
Normal file
220
third_party/glog/src/glog/stl_logging.h.in
vendored
Normal 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_
|
||||
129
third_party/glog/src/glog/vlog_is_on.h.in
vendored
Normal file
129
third_party/glog/src/glog/vlog_is_on.h.in
vendored
Normal 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
611
third_party/glog/src/googletest.h
vendored
Normal 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
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
79
third_party/glog/src/logging_striplog_test.sh
vendored
Executable 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"
|
||||
35
third_party/glog/src/logging_striptest10.cc
vendored
Normal file
35
third_party/glog/src/logging_striptest10.cc
vendored
Normal 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"
|
||||
35
third_party/glog/src/logging_striptest2.cc
vendored
Normal file
35
third_party/glog/src/logging_striptest2.cc
vendored
Normal 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"
|
||||
73
third_party/glog/src/logging_striptest_main.cc
vendored
Normal file
73
third_party/glog/src/logging_striptest_main.cc
vendored
Normal 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
1348
third_party/glog/src/logging_unittest.cc
vendored
Normal file
File diff suppressed because it is too large
Load diff
307
third_party/glog/src/logging_unittest.err
vendored
Normal file
307
third_party/glog/src/logging_unittest.err
vendored
Normal 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
156
third_party/glog/src/mock-log.h
vendored
Normal 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
106
third_party/glog/src/mock-log_test.cc
vendored
Normal 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();
|
||||
}
|
||||
8
third_party/glog/src/package_config_unittest/working_config/CMakeLists.txt
vendored
Normal file
8
third_party/glog/src/package_config_unittest/working_config/CMakeLists.txt
vendored
Normal 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)
|
||||
6
third_party/glog/src/package_config_unittest/working_config/glog_package_config.cc
vendored
Normal file
6
third_party/glog/src/package_config_unittest/working_config/glog_package_config.cc
vendored
Normal 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
158
third_party/glog/src/raw_logging.cc
vendored
Normal 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
403
third_party/glog/src/signalhandler.cc
vendored
Normal 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_
|
||||
112
third_party/glog/src/signalhandler_unittest.cc
vendored
Normal file
112
third_party/glog/src/signalhandler_unittest.cc
vendored
Normal 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
131
third_party/glog/src/signalhandler_unittest.sh
vendored
Executable 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
61
third_party/glog/src/stacktrace.h
vendored
Normal 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_
|
||||
59
third_party/glog/src/stacktrace_generic-inl.h
vendored
Normal file
59
third_party/glog/src/stacktrace_generic-inl.h
vendored
Normal 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_
|
||||
90
third_party/glog/src/stacktrace_libunwind-inl.h
vendored
Normal file
90
third_party/glog/src/stacktrace_libunwind-inl.h
vendored
Normal 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_
|
||||
130
third_party/glog/src/stacktrace_powerpc-inl.h
vendored
Normal file
130
third_party/glog/src/stacktrace_powerpc-inl.h
vendored
Normal 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_
|
||||
217
third_party/glog/src/stacktrace_unittest.cc
vendored
Normal file
217
third_party/glog/src/stacktrace_unittest.cc
vendored
Normal 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
|
||||
50
third_party/glog/src/stacktrace_windows-inl.h
vendored
Normal file
50
third_party/glog/src/stacktrace_windows-inl.h
vendored
Normal 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_
|
||||
146
third_party/glog/src/stacktrace_x86-inl.h
vendored
Normal file
146
third_party/glog/src/stacktrace_x86-inl.h
vendored
Normal 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_
|
||||
105
third_party/glog/src/stacktrace_x86_64-inl.h
vendored
Normal file
105
third_party/glog/src/stacktrace_x86_64-inl.h
vendored
Normal 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_
|
||||
197
third_party/glog/src/stl_logging_unittest.cc
vendored
Normal file
197
third_party/glog/src/stl_logging_unittest.cc
vendored
Normal 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
966
third_party/glog/src/symbolize.cc
vendored
Normal 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
158
third_party/glog/src/symbolize.h
vendored
Normal 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_
|
||||
425
third_party/glog/src/symbolize_unittest.cc
vendored
Normal file
425
third_party/glog/src/symbolize_unittest.cc
vendored
Normal 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
374
third_party/glog/src/utilities.cc
vendored
Normal 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
238
third_party/glog/src/utilities.h
vendored
Normal 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__
|
||||
58
third_party/glog/src/utilities_unittest.cc
vendored
Normal file
58
third_party/glog/src/utilities_unittest.cc
vendored
Normal 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
257
third_party/glog/src/vlog_is_on.cc
vendored
Normal 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
21
third_party/glog/src/windows/config.h
vendored
Executable 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
1160
third_party/glog/src/windows/dirent.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
96
third_party/glog/src/windows/glog/log_severity.h
vendored
Normal file
96
third_party/glog/src/windows/glog/log_severity.h
vendored
Normal 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
1690
third_party/glog/src/windows/glog/logging.h
vendored
Executable file
File diff suppressed because it is too large
Load diff
184
third_party/glog/src/windows/glog/raw_logging.h
vendored
Executable file
184
third_party/glog/src/windows/glog/raw_logging.h
vendored
Executable 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_
|
||||
224
third_party/glog/src/windows/glog/stl_logging.h
vendored
Executable file
224
third_party/glog/src/windows/glog/stl_logging.h
vendored
Executable 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
133
third_party/glog/src/windows/glog/vlog_is_on.h
vendored
Executable 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
65
third_party/glog/src/windows/port.cc
vendored
Executable 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
174
third_party/glog/src/windows/port.h
vendored
Executable 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
119
third_party/glog/src/windows/preprocess.sh
vendored
Executable 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"
|
||||
Loading…
Add table
Add a link
Reference in a new issue